• 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

  • 相关阅读:
    快速排序的分析与优化
    矩阵原地转置
    变位词问题
    一维向量旋转算法
    位图排序
    Linux网络编程:UDP实现可靠的文件传输
    Linux网络编程:UDP Socket编程范例
    es6+最佳入门实践(6)
    es6+最佳入门实践(5)
    es6+最佳入门实践(4)
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9808306.html
Copyright © 2020-2023  润新知