poj 3254 Corn Fields (状压DP)
2015-10-07 11:16
351 查看
题目大意: N*M的农场, 有的格子可以放牛,有的不行。在这块地方放牛,相邻的格子不能有牛。求方案数。
N、M都比较小(<13),那么可以用1个2进制位表示一行中的每一个格子的状态,0表示不放牛,1表示放牛,一行中的所有二进制位构成一个状态s。
设dp[i][s]表示第i行状态为s时的方案数。那么状态转移方程:dp[i][s]=∑(dp[i−1][s′])
其中s’为i-1行的状态,且满足s和s’相同位不同时为1。
注意在枚举某一行i的状态的时候,有的状态是不合法的,可以通过奇妙的位运算来判别这些不合法的状态。比如判断状态s中是否存在两个相邻的1,判定s&(s>>1)是否为1即可。
N、M都比较小(<13),那么可以用1个2进制位表示一行中的每一个格子的状态,0表示不放牛,1表示放牛,一行中的所有二进制位构成一个状态s。
设dp[i][s]表示第i行状态为s时的方案数。那么状态转移方程:dp[i][s]=∑(dp[i−1][s′])
其中s’为i-1行的状态,且满足s和s’相同位不同时为1。
注意在枚举某一行i的状态的时候,有的状态是不合法的,可以通过奇妙的位运算来判别这些不合法的状态。比如判断状态s中是否存在两个相邻的1,判定s&(s>>1)是否为1即可。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; #define mod 100000000 #define maxn 1<<12 LL dp[12][maxn]; int cur[12]; inline bool check1(int i,int s) { if((cur[i]&s)!=s) return 0; if(s&(s>>1)) return 0; return 1; } inline bool check2(int s1,int s2) { if(s1&s2) return 0; return 1; } int main() { int n,m,i,j,k,a,M; while(~scanf("%d%d",&n,&m)){ memset(dp,0,sizeof(dp)); M=(1<<m); for(i=0;i<n;++i){ cur[i]=0; for(j=0;j<m;++j) { scanf("%d",&a); cur[i]=(cur[i]<<1)+a; } } for(j=0;j<M;++j) if(check1(0,j)) ++dp[0][j]; for(i=1;i<n;++i) for(j=0;j<M;++j) { if(!check1(i,j)) continue; for(k=0;k<M;++k) { if(!check2(j,k)) continue; dp[i][j]+=dp[i-1][k]; if(dp[i][j]>mod) dp[i][j]-=mod; } } LL ans=0; for(i=0;i<M;++i) ans=(ans+dp[n-1][i])%mod; printf("%I64d\n",ans); } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)
- Word Break I,II, Triangle,Palindrome Partitioning 动态规划 DP