SCOI2008着色方案(记忆化搜索)

本文介绍了一个使用记忆化搜索算法解决木块染色问题的方法。问题设定为有n个木块排成一行,用k种颜色进行染色,每种颜色的木块数量已知,目标是统计所有相邻木块颜色不同的染色方案。通过设计状态dp记录每种颜色的数量及上一次染色的状态,实现高效求解。

有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i 种颜色的油漆足够涂ci 个木块。所有油漆刚好足够涂满所有木块,即

c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。

Solution

有一个非常好的条件就是c[i]<=5,这样我们就可以设计状态为dp[1][2][3][4][5][la]表示有一个的有几种颜色,有两个的有几种颜色·····,上一次我们枚举的是哪里。

然后就愉快的记忆化搜索,注意要求相邻木块颜色不同的条件:例如我当前枚举1,如果我上一次枚举的二,那么有一个一我就不能选。

Code

#include<iostream>
#include<cstring>
#include<cstdio>
#define mod 1000000007
using namespace std;
typedef long long ll;
int dp[16][16][16][16][16][6],n,ji[9],x;
int dfs(int one,int sec,int thi,int fou,int fiv,int hea){
    if(~dp[one][sec][thi][fou][fiv][hea])return dp[one][sec][thi][fou][fiv][hea];
    long long ans=0;
    if(one)(ans+=((ll)one-(hea==1))*dfs(one-1,sec,thi,fou,fiv,0))%=mod;
    if(sec)(ans+=((ll)sec-(hea==2))*dfs(one+1,sec-1,thi,fou,fiv,1))%=mod;
    if(thi)(ans+=((ll)thi-(hea==3))*dfs(one,sec+1,thi-1,fou,fiv,2))%=mod;
    if(fou)(ans+=((ll)fou-(hea==4))*dfs(one,sec,thi+1,fou-1,fiv,3))%=mod;
    if(fiv)(ans+=(ll)fiv*dfs(one,sec,thi,fou+1,fiv-1,4))%=mod;
    return dp[one][sec][thi][fou][fiv][hea]=ans;
}
int main(){
    scanf("%d",&n);
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<=5;++i)dp[0][0][0][0][0][i]=1; 
    for(int i=1;i<=n;++i)scanf("%d",&x),ji[x]++;
    printf("%d",dfs(ji[1],ji[2],ji[3],ji[4],ji[5],5));
    return 0;
}

 

转载于:https://www.cnblogs.com/ZH-comld/p/9814320.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值