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

Input

  输入共三行。
  第一行: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
 
 
 
 
三进制状压,预处理合法状态以及能互相兼容的合法状态
然后分类计算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

posted @ 2018-10-18 07:43  saionjisekai  阅读(76)  评论(0编辑  收藏  举报