2019.9.1 涂抹果酱

Posted qxds

tags:

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

技术图片

 

 技术图片


 

还是简单的状压dp

用dp[i][j]表示前i行最后一行状态是j的方案总数

则每次判断当前是普通行、已经固定的行、固定行的下一行

如果是普通行 dp[i][j]+=dp[i-1][l]

如果是固定行 记已经固定好的状态编号是flag 则dp[i][flag]+=dp[i-1][l]且dp[i][j](j!=flag)=0

如果是固定行的下一行 则dp[i][j]+=dp[i-1][flag]

注意由于是1-3所以用4进制状态压缩 所有含有0的状态全部排除

上代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
using namespace std;
int cnt,num[10050],dp[10050][(2<<12)+1];
int n,m,k,mapp[10050],ans,book;
bool check(int x)

    int flag=-1;
    if(x==0)return false;
    int idx=0;
    int temp=x;
    while(temp)
    
        if(!(temp%4))return false;
        idx++;
        temp/=4;
    
    if(idx<m)return false;
    while(x)
    
        if(flag==x%4)return false;
        flag=x%4;
        x/=4;
    
    return true;
//判断状态本身是否合法
bool cannot(int x,int y)

    while(x)
    
        int p=x%4,q=y%4;
        if(p==q)return true;
        x/=4,y/=4;
    
    return false;
//判断两个状态能否作为上下两行同时出现
signed main()

    scanf("%lld%lld",&n,&m);
    scanf("%lld",&k);
    for(int i=1;i<=m;i++)scanf("%lld",&mapp[i]),book=book*4+mapp[i];
    if(!check(book))//特判,如果固定行的状态不合法
    
        putchar(0);
        return 0;
    
    int maxn=1;
    for(int i=1;i<=m;i++)maxn*=4;
    --maxn;
    for(int i=0;i<=maxn;i++)
        if(check(i))//枚举可能的状态
        
            //printf("%d\\n",i);
            num[++cnt]=i,dp[1][cnt]=1;
        
    int flag=-1;
    for(int j=1;j<=cnt;j++)
        if(num[j]==book)
        
            flag=j;
            break;
        //记录固定行状态编号
    for(int i=1;i<=cnt;i++)
        if(i!=flag)dp[k][i]=0;//将所有固定行没有选择固定行状态的dp值全部置0
    for(int i=2;i<=n;i++)
    
        if(i==k)//固定行
        
            for(int j=1;j<=cnt;j++)
                if(j!=flag)dp[i][j]=0;
            for(int l=1;l<=cnt;l++)
                if(!cannot(num[l],book))dp[i][flag]=(dp[i][flag]+dp[i-1][l])%1000000;//枚举上一行的状态,记得加的时候取模
            continue;
        
        for(int j=1;j<=cnt;j++)
        
            int x=num[j];
            if(i==k+1)//固定行的上一行
            
                if(cannot(x,book))continue;
                dp[i][j]=(dp[i][j]+dp[i-1][flag])%1000000;
                continue;
            
            for(int l=1;l<=cnt;l++)
            
                int y=num[l];
                if(cannot(x,y))continue;
                dp[i][j]=(dp[i][j]+dp[i-1][l])%1000000;
            //普通行
        
    
    for(int i=1;i<=cnt;i++)
    
        ans=(ans+dp[n][i])%1000000;//枚举最后一行可能的状态
        //printf("%lld ",ans);
    
    printf("%lld",ans);
    return 0;

 

以上是关于2019.9.1 涂抹果酱的主要内容,如果未能解决你的问题,请参考以下文章

涂抹果酱

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

涂抹果酱

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

三进制状压(涂抹果酱)

s3eSocket 果酱无法创建套接字