poj3254 状压DP

来源:互联网 发布:方正字体投诉淘宝店铺 编辑:程序博客网 时间:2024/04/27 15:00
/*真值表:a为状态(放牛为1,不放牛为0);b为场地状态(1为可以放,0为不能放)    a   b    F    0   0    1  //不放牛 场地也不允许放  没问题真值为1    0   1    1  //不放牛 场地可以放  没问题    1   0    0  //放牛    但场地不能放  错误 真值为0    1   1    1  //放牛 场地可以放  没问题    由真值表 得F=(~a)|b=!(a&(~b)); 可以看到b是要取反的 所以在读入的时候要对场地取反*/#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#define LL long long#define maxn 1<<12#define MOD 100000000using namespace std;int state[maxn];//填充一行 ,所有可行状态int current_state[13];//i行的场地状况int num_state;//state的大小int dp[13][maxn];//dp[i][j]  i为行数  j为第j个状态bool state_ok(int x,int y)//检验状态x和状态y能否相邻 不能 return 0 否则return 1;{    return !(x&y); //相邻状态不能同时为1}void find_state_of_one_row(int  m)//寻找填充一行(该行所有的格子都是1,都是fertile)的所有可行状态{    int i;    num_state=0;    m=1<<m;    for(i=0;i<m;++i)    {        if(state_ok(i,i<<1))//将状态i平移一位,检验是否有两只羊相邻的情况        {            state[num_state++]=i;        }    }    return ;}int main(){    memset(dp,0,sizeof(dp));    memset(current_state,0,sizeof(current_state));    int n,m;    scanf("%d%d",&n,&m);    int i,j;    for(i=0;i<n;++i)    {        for(j=0;j<m;++j)        {            int temp;            scanf("%d",&temp);            if(!temp)            {                current_state[i]+=(1<<j);                //F=(~a)|b=!(a&(~b)); a为填充一行的可行状态,b为当前场地的状态(能不能放牛);此处为对b取反 即(~b)            }        }    }    find_state_of_one_row(m);    for(i=0;i<num_state;++i)//初始化第一行的可行状态数    {        if(state_ok(state[i],current_state[0]))//判断该状态能否放在该行 F=(~a)|b=!(a&(~b));  state为a , current_state为(~b)        {            dp[0][i]=1;        }    }    int k;    for(i=1;i<n;++i)    {        for(j=0;j<num_state;++j)//选取上一行的可用状态        {            if(dp[i-1][j]==0) continue;            for(k=0;k<num_state;++k)//选取本行的状态            {                if(state_ok(state[k],current_state[i]) && state_ok(state[j],state[k]))//该状态可以放到i行并且可以和上一行的j状态相邻                {                    dp[i][k]=(dp[i][k]+dp[i-1][j])%MOD;//第k个状态可行 并且可能有多个j状态可以与k状态相邻  所以是+=;                }            }        }    }    int ans=0;    for(i=0;i<num_state;++i)    {        ans=(ans+dp[n-1][i])%MOD;    }    printf("%d\n",ans);}

0 0
原创粉丝点击