10.17T7 三进制状压DP
Description
Tyvj两周年庆典要到了,Sam想为Tyvj做一个大蛋糕。蛋糕俯视图是一个N*M的矩形,它被划分成N*M个边长为1*1的小正方形区域。(可以把蛋糕当成N行M列的矩阵)蛋糕很快做好了,但光秃秃的蛋糕…肯定不好看!所以,Sam要在蛋糕的上表面涂抹果酱。果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为1,2,3。为了保证蛋糕的视觉效果,Admin下达了死命令:相邻的区域严禁使用同种果酱。但…Sam在接到这条命令之前,已经涂好了蛋糕第K行的果酱,且无法修改。
现在,Sam想知道,能令Admin满意的涂果酱方案有多少种(mod 10^6)。若不存在这种方案,请输出0
现在,Sam想知道,能令Admin满意的涂果酱方案有多少种(mod 10^6)。若不存在这种方案,请输出0
Input
输入共三行。
第一行:N,M
第二行:K
第三行:M个整数,表示第K行的方案
字母的详细含义见题目描述,其他参见样例
第一行:N,M
第二行:K
第三行:M个整数,表示第K行的方案
字母的详细含义见题目描述,其他参见样例
Output
共一行:可行的方案总数。
Sample Input
2 2
1
2 3
Sample Output
3
Hint
【样例说明】
第一行的2 3是固定的,合理的果酱涂抹方案共3种:
--方案1--
2 3
1 2
--方案2--
2 3
3 1
--方案3--
2 3
3 2
【数据范围】
对于30%的数据,1<=N*M<=20
对于60%的数据,1<=N<=1000,1<=M<=3
对于100%的数据,1<=N<=10000,1<=M<=5
第一行的2 3是固定的,合理的果酱涂抹方案共3种:
--方案1--
2 3
1 2
--方案2--
2 3
3 1
--方案3--
2 3
3 2
【数据范围】
对于30%的数据,1<=N*M<=20
对于60%的数据,1<=N<=1000,1<=M<=3
对于100%的数据,1<=N<=10000,1<=M<=5
三进制状压,预处理合法状态以及能互相兼容的合法状态
然后分类计算K之前的行数和K之后的行数,最后加上最后一行的所有合法状态的方案数
我这里特判了m=1这种情况,总的说来不算是很难的一道题
code:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int mod=1e6; 5 int f[10005][300],is[300][300],n,m,a[300],cnt; 6 bool check(int x) { 7 int tmp=1; 8 int last=x%(tmp*3)/tmp; 9 for(int i=2; i<=m; i++) { 10 tmp*=3; 11 int x1=x%(tmp*3)/tmp; 12 if(last==x1)return false; 13 last=x1; 14 } 15 return true; 16 } 17 bool check2(int x,int y) { 18 int tmp=1; 19 for(int i=1; i<=m; i++) { 20 int x1=x%(tmp*3)/tmp; 21 int y1=y%(tmp*3)/tmp; 22 if(x1==y1)return false; 23 tmp*=3; 24 } 25 return true; 26 } 27 int main() { 28 cin>>n>>m; 29 int all=1; 30 for(int i=1; i<=m; i++)all*=3; 31 for(int i=0; i<=all; i++) { 32 if(check(i)) { 33 a[++cnt]=i; 34 } 35 } 36 for(int i=1; i<=cnt; i++) { 37 for(int j=1; j<=cnt; j++) { 38 if(check2(a[i],a[j])) { 39 is[a[i]][a[j]]=1; 40 } 41 } 42 } 43 // is[0][0]=1; 44 int K; 45 cin>>K; 46 int S=0; 47 //if(K==1)return -1; 48 //if(n==1)return -1; 49 for(int i=1; i<=m; i++) { 50 int x; 51 cin>>x; 52 x--; 53 S=S*3+x; 54 } 55 if(m==1){ 56 int ans=1; 57 for(int i=1;i<n;i++){ 58 ans*=2; 59 ans%=mod; 60 } 61 cout<<ans; 62 return 0; 63 } 64 if(check(S)==0) { 65 cout<<0; 66 return 0; 67 } 68 if(K==1) { 69 f[K][S]=1; 70 } else { 71 for(int i=1; i<=cnt; i++)f[1][a[i]]=1; 72 for(int i=2; i<K; i++) { 73 for(int j=1; j<=cnt; j++) { 74 for(int k=1; k<=cnt; k++) { 75 if(is[a[j]][a[k]]) { 76 f[i][a[k]]+=f[i-1][a[j]]; 77 f[i][a[k]]%=mod; 78 } 79 } 80 } 81 } 82 for(int i=1; i<=cnt; i++) { 83 if(is[a[i]][S]) { 84 f[K][S]+=f[K-1][a[i]]; 85 f[K][S]%=mod; 86 } 87 } 88 } 89 for(int i=K+1; i<=n; i++) { 90 for(int j=1; j<=cnt; j++) { 91 for(int k=1; k<=cnt; k++) { 92 if(is[a[j]][a[k]]) { 93 f[i][a[k]]+=f[i-1][a[j]]; 94 f[i][a[k]]%=mod; 95 } 96 } 97 } 98 } 99 int ans=0; 100 for(int i=1; i<=cnt; i++) { 101 // cout<<n<<" "<<i<<" "<<f[n][i]<<endl; 102 ans+=f[n][a[i]],ans%=mod; 103 } 104 cout<<ans; 105 return 0; 106 }
over