码迷,mamicode.com
首页 > 其他好文 > 详细

三进制状压(涂抹果酱)

时间:2020-03-16 19:20:45      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:idt   sam   一起   等于   clu   thml   math   命令   for   

题意:https://www.acwing.com/problem/content/1067/

Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕。

蛋糕俯视图是一个 N×M 的矩形,它被划分成 N×M 个边长为 1×1×1 的小正方形区域(可以把蛋糕当成 N 行 M 列的矩阵)。

蛋糕很快做好了,但光秃秃的蛋糕肯定不好看!

所以,Sam 要在蛋糕的上表面涂抹果酱。

果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为 1,2,3。

为了保证蛋糕的视觉效果,Admin 下达了死命令:相邻的区域严禁使用同种果酱。

但 Sam 在接到这条命令之前,已经涂好了蛋糕第 K 行的果酱,且无法修改。

现在 Sam 想知道:能令 Admin 满意的涂果酱方案有多少种。请输出方案数 mod106。

若不存在满足条件的方案,请输出 0。


三进制状压,因为多了一种状态所以没办法用位运算简便的判断。

所以我们可以自己写函数。

#include <bits/stdc++.h>
typedef long long ll;
const int mod=1000000;
using namespace std;
int n,m,k,stat=1,cnt=1,ban;//stat是总的状态数,ban是第K行的状态 
int sta[1009],dp[10009][1005];
bool check(int x){//检验是否有相邻的数 
    int temp=-1;
    for(int i=1;i<=m;i++){
        if(temp==x%3)    return false;//等于上一个数就不行 
        temp=x%3,x/=3;
    }
    return true;
}
bool judge(int l,int r){
    for(int i=1;i<=m;i++){
        if(l%3==r%3)    return false;
        l/=3,r/=3;
    }
    return true;
}
int main()
{
    cin>>n>>m>>k;
    stat=ll(pow(3,m));
    for(int i=0;i<stat;i++)
        if(check(i))    sta[cnt++]=i;
    int z;
    for(int i=1;i<=m;i++)//读入第K行的状态
    {
        cin>>z;
        ban=ban*3+z-1; 
    }
    if(!check(ban))    {cout<<0;return 0;}//第K行连在了一起
    int num;//记录第K行对应的下标 
    for(int i=1;i<cnt;i++)    if(ban==sta[i])    num=i;
    for(int i=1;i<=n;i++)
    {
        if(i==k){
            if(i==1)    dp[1][num]=1;
            else{
                for(int j=1;j<cnt;j++){
                    if(judge(sta[num],sta[j]))
                        dp[i][num]=(dp[i][num]+dp[i-1][j])%mod;
                }
            }
            continue;    
        }
        for(int j=1;j<cnt;j++)//枚举状态
        {
            if(i==1)    dp[i][j]=1;
            else{
                for(int k=1;k<cnt;k++)
                {
                    if(judge(sta[j],sta[k]))//两行的状态不冲突
                        dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; 
                }
            }
         } 
     }
     ll ans=0;
     for(int i=1;i<cnt;i++)    ans=(ans+dp[n][i])%mod;
     cout<<ans; 
}

 

三进制状压(涂抹果酱)

标签:idt   sam   一起   等于   clu   thml   math   命令   for   

原文地址:https://www.cnblogs.com/iss-ue/p/12505573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!