poj3254(常见的二维状压dp)
2017-01-01 01:19
162 查看
/* translation: 给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法 solution: 状态压缩dp 每次枚举时候判断是否符合当前草地的情况,再判断是否跟前面的一行兼容。 note: * 将所有合法状态预先处理存进一个数组里面即可提高速度 # 一开始check(i, s)WA了好多次,后来发现应该是check(i, st[s])。 date: 2017.1.1-----跨年快乐。 */ #include <iostream> #include <cstdio> #include <cstring> typedef long long ll; using namespace std; const int maxn = 15; const int mod = 100000000; int dp[maxn][1 << maxn], m, n, G[maxn][maxn]; int st[1 << maxn]; //存放预处理求出的符合要求的状态 void init() { int id = 0; memset(st, 0, sizeof(st)); for(int i = 0; i < 1 << maxn; i++) if(!(i & (i << 1))){ st[id++] = i; //将所有不相邻的状态存放进st数组当中 } } bool check(int row, int s) //检查在第row行的s状态是否非法 { for(int i = 0; i < n; i++){ if((s >> i & 1) && !G[row][i]) return false; } return true; } int main() { //freopen("in.txt", "r", stdin); init(); while(~scanf("%d%d", &m, &n)){ //m--行 n--列 memset(G, 0, sizeof(G)); memset(dp, 0, sizeof(dp)); for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ scanf("%d", &G[i][j]); } } //dp[i][s]表示到目前第i行的s状态为止,总共有多少种方案 for(int i = 0; st[i] < 1 << n; i++) if(check(0, st[i]))dp[0][i] = 1; for(int i = 1; i < m; i++){ for(int pres = 0; st[pres] < 1 << n; pres++){ //枚举前一行的状态 for(int s = 0; st[s] < 1 << n; s++) if(!(st[s] & st[pres]) && check(i, st[s])){ //枚举当前行的状态 dp[i][s] += dp[i-1][pres]; } } } ll res = 0; for(int s = 0; st[s] < 1 << n; s++){ res += dp[m-1][s]; } printf("%d\n", res % mod); } return 0; }
相关文章推荐
- HTML5 表单元素
- HTML5 新的 Input 类型
- 面对2016,我挥一挥衣袖
- HTML5 Audio(音频)
- 【zju2112/bzoj1901】Dynamic Rankings
- 【题】【搜索(预处理剪枝)】NOIP2009 靶形数独
- 联想笔记本连不上网手机可以的解决办法 wifi适配器的驱动程序可能出现问题的解决办法
- Python转换IP为具体地理位置小脚本
- HTML5 Video(视频)
- 1424. 奖金
- HTML5 Geolocation(地理定位)
- HTML5 拖放(Drag 和 Drop)
- 半监督学习里高斯混合模型的推导证明
- NodeJS-http
- HTML5 MathML
- HTML5 内联 SVG
- 和牛腩学编程路线图
- HTML5 Canvas
- 和牛腩学编程路线图
- C++:编写跨平台程序的关键,C/C++中的内置宏定义