三进制状压(涂抹果酱)

Posted iss-ue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三进制状压(涂抹果酱)相关的知识,希望对你有一定的参考价值。

题意: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; 
}

 

以上是关于三进制状压(涂抹果酱)的主要内容,如果未能解决你的问题,请参考以下文章

#10172. 「一本通 5.4 练习 1」涂抹果酱 题解

涂抹果酱

「一本通 5.4 练习 1」涂抹果酱

2019.9.1 涂抹果酱

涂抹果酱

hdu 3001(三进制状压)