POJ 3254 Corn Fields 状态压缩dp入门

来源:互联网 发布:redis存储数据大小 编辑:程序博客网 时间:2024/05/01 14:45

原文:http://blog.csdn.net/y990041769/article/details/24658419

在原文基础上,加上自己的理解

状态压缩dp入门

1、二进制的移动知识基础:

#include <cstdio>int main(){int k=5;printf("%d\n", 1<<k);// 1 向左移动k位 100000,2^5 32printf("%d\n", 1>>k);// 1 向右移动k位 0.00001,为0 printf("%d\n", k<<1);// k 向左移动1位 101 -> 1010 即k*2=10printf("%d\n", k>>1);// k 向右移动1位 101 -> 10.1 即k/2=2return 0;}

 2、& 的妙用

同为1 才为1,不然就是0,

很巧妙的相错开来


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std; const int N=15;const int M=1<<N;//10000000000000const int mod = 100000000;int st[M],mp[M];int dp[N][M];//表示dp[i][j] 在i行 状态为j时 放牛的种数 int jud1(int x){//相邻是否一样  return (x&(x<<1));}int jud2(int i,int x){return (mp[i]&st[x]);}int main(){int n,m,x;while(~scanf("%d%d",&n,&m)){memset(st,0,sizeof(st));memset(mp,0,sizeof(mp));memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&x);if(x==0)//第i行的土地状况 可以累加出来 //而且这个土地情况 是 与真实的是相反的 mp[i]=mp[i]+(1<<(j-1)); }}int k=0;//枚举m位 不同的0,1情况//只有相邻不同的数,左移一位相互交错,数值为0 //st[] 存每一行相互交错的情况 ,总交错状态数为 k for(int tm=0;tm<(1<<m);tm++){if(  !jud1(tm)  )st[k++]=tm;}for(int j=0;j<k;j++){// 找出与第一行土地 状态为j ,且与土地交错的// 那么初始化为1 if( !jud2(1,j) )dp[1][j]=1;}for(int i=2;i<=n;i++){                 //枚举行数 for(int j=0;j<k;j++){              //枚举上一行的状态数 //一:第i行状态j 与 第i行土地交错if(jud2(i,j))continue;for(int f=0;f<k;f++){          //枚举下一行的状态数 //二:与第i行的上一行的土地也要交错  if(jud2(i-1,f))continue;//三:上一行状态j 和这一行状态f 也要交错 if(!(st[j]&st[f]))dp[i][j]+=dp[i-1][f];}}}//dp[最后一行][不同方案] 总值累加起来,就是结果   int ans=0;for(int j=0;j<k;j++){ans+=dp[n][j];ans%=mod;}printf("%d\n",ans);}return 0;}


0 0
原创粉丝点击