状压dp

洛谷1879(大概算板子题叭。。

看数据范围应该是状压dp,通过二进制01表示状态。

#include <iostream>
using namespace std;
const int maxn=100000000;
int state[13],dp[13][(1<<12)+3];
bool jdg[(1<<12)+3];

int main(){
    int m,n,x;
    cin>>m>>n;
    for(int i=1;i<=m;++i){
        for(int j=1;j<=n;++j){
            cin>>x;
            state[i]=(state[i]<<1)+x;//state[i]表示第i行的草地情况
        }
    }
    int max_state=1<<n;//最大状态
                       //从0~max_state-1这些状态里找合法状态
    for(int i=0;i<max_state;++i){  //同一行不相邻
        if((i&(i<<1))==0){   //左移右移选一个即可
            jdg[i]=true;
        }
    }
    dp[0][0]=1;//初始化,可以保证真正第一行状态的正确性
    for(int i=1;i<=m;++i){//第i行
        for(int j=0;j<max_state;++j){//状态为j
            if(jdg[j]&&((j&state[i])==j)){   //同一行不相邻&&草没种在贫瘠的地方
                for(int k=0;k<max_state;++k){ //枚举上一行的状态
                    if((j&k)==0){        //同一列不相邻
                        dp[i][j]+=dp[i-1][k];
                        dp[i][j]%=maxn;
                    }
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<max_state;++i){//把最后一行都加起来即可
        ans+=dp[m][i];
        ans%=maxn;
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2020-07-30 15:49  .Ivorelectra  阅读(74)  评论(0编辑  收藏  举报