状态压缩dp例题
2015-06-04 21:30
239 查看
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string.h> #include <queue> #include <vector> #define LL long long #define N 10010 #define mod 100000000 //poj3254 using namespace std; LL ans, dp[12][1<<12], kind[1<<12]; /* 题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示, 在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案) 思路:状态压缩dp,预处理kind数组内合法的方法(牛同行左右互不相邻),状态转移方程为dp[i][j]+=dp[i-1][t]----其中i-1行的状态t要和i行的状态j不冲突 */ int a[12]; bool check1(int x) { int flag=0; while(x) { if(x&1) { if(flag) return false; else flag=1; } else flag=0; x>>=1; } return true; } bool check2(int x, int k) //判断实际的放置方案符不符合题目要求 { if(kind[x]&&(x|a[k])==a[k]) return true; return false; } int main() { int n, m, i, t, j, g, k; g=1<<12; for(t=0; t<g; ++t) { if(check1(t)) kind[t]=1; } while(scanf("%d%d", &n, &m)!=EOF) { memset(dp, 0, sizeof(dp)); memset(a, 0, sizeof(a)); for(j=0; j<n; ++j) { for(t=0; t<m; ++t) { scanf("%d", &g); a[j]=a[j]*2+g; } } k=1<<m; for(t=0; t<k; ++t) { if(check2(t, 0)) dp[0][t]=1; } for(i=1; i<n; ++i) { for(j=0; j<k; ++j) { for(t=0; t<k; ++t) { if(check2(t, i-1)&&check2(j, i)&&((j&t)==0)) dp[i][j]+=dp[i-1][t]; } dp[i][j]%=mod; } } for(t=0, ans=0; t<k; ++t) { if(dp[n-1][t]) ans+=dp[n-1][t]; ans%=mod; } printf("%I64d\n", ans); } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string.h> #include <queue> #include <vector> #define LL long long #define N 10010 using namespace std; LL dp[1<<11][11], kind[1<<11]; int k; //poj2411 /* 题意:一个矩阵,只能放1*2的木块,问将这个矩阵完全覆盖的不同放法有多少种 思路:dp状态压缩,11表示横放,0表示在该行放竖(下一行对应为1) */ bool check1(int x) { int g=0; while(x) { if(x&1) g++; else { if(g&1) return false; else g=0; } x>>=1; } if(g&1) return false; else return true; } bool check2(int j, int t) { if((j|t)!=k-1) return false; if(kind[j&t]) //这里状态j和状态t不起冲突,它们的不一定kind值都要为1,如1000 | 0111 ,但是1100和0111不行 return true; else return false; } int main() { int n, m, i, t, j; k=1<<11; for(t=0; t<k; ++t) //枚举各种合法状态 { if(check1(t)) kind[t]=1; } while(scanf("%d%d", &n, &m)&&n&&m) { if(n*m%2) { printf("0\n"); continue; } memset(dp, 0, sizeof(dp)); k=1<<m; for(t=0; t<k; ++t) { if(kind[t]) dp[t][0]=1; } for(i=1; i<n; ++i) { for(j=0; j<k; ++j) { for(t=0; t<k; ++t) { if(!check2(j, t)) continue; dp[j][i]+=dp[t][i-1]; } } } printf("%I64d\n", dp[k-1][n-1]); //最后一行肯定都是1 } return 0; }
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <queue> using namespace std; //poj1185 炮兵阵地 /* 总结:这道题和上面的状态压缩不一样,因为如果表示全部状态的话空间不够(其中也包括无用的状态),实际有效的状态只有70以内 在这里用一个数组s来存储其各个状态 */ int n, m, T; int s[70]; //存放炮兵不同的排列状态的数组,最多只有几十种 int sum[70]; //炮兵不同的排列中1的数量 int dp[105][70][70]; //dp[i][j][k]第一维表示行,第二维表示第i行状态为s[j],第三维表示第i-1行状态为s[k] int map[105]; char a[105][12]; int ok(int x) //炮兵占有的位为1,没占有的为0 { //避免同一行的冲突 if(x&(x<<1))return 0; if(x&(x<<2))return 0; return 1; } int getsum(int x) //计算一个状态里1的个数 { int s1=0; while(x>0) { if(x&1) s1++; x=x>>1; } return s1; } void search() //预处理计算实际可以用的状态总数 { int j, k; k=1<<m; for(j=T=0; j<k; ++j) { if(ok(j)) { s[T]=j; sum[T++]=getsum(j); } } return ; } int main() { int i, t, j, k, g, p, s2; scanf("%d%d", &n, &m); for(t=0; t<n; ++t) scanf("%s", &a[t]); for(j=0; j<n; ++j) { for(t=0; t<m; ++t) { if(a[j][t]=='P') map[j]+=(1<<t); } } search(); for(t=0; t<T;++t) //与实际情况结合 if((map[0]|s[t])==map[0]) dp[0][t][0]=sum[t]; for(i=1; i<n; ++i) { for(j=0; j<T; ++j) { if((map[i]|s[j])!=map[i])continue; for(k=0; k<T; ++k) { if(s[j]&s[k]||(map[i-1]|s[k])!=map[i-1])continue; for(t=0; t<T; ++t) { if(s[t]&s[j]||s[t]&s[k])continue; dp[i][j][k]=max(dp[i][j][k], dp[i-1][k][t]+sum[j]); } } } } for(j=s2=0; j<T; ++j) { for(t=0; t<T; ++t) { if(dp[n-1][j][t]>s2) s2=dp[n-1][j][t]; } } printf("%d\n", s2); return 0; }
相关文章推荐
- Microsoft TPL Dataflow 并行处理枚举,输出等
- CSS伪类和伪元素
- JSTL 核心标签库 使用
- 完整Debian7配置LAMP(Apache/MySQL/PHP)环境及搭建建站
- MySQL(必须要的基础配置)
- Deep Learning源代码收集-持续更新…
- 查询评论接口优化案例
- 《软件工程》课程改进意见
- 图像处理 频域滤波函数
- hdu - 5242 Game(链剖分)
- Java反射(一)
- 安装并使用PICT,生成测试用例
- 使用Python扫描端口
- 实现护士工作站的注射室管理功能的代码(十六)
- quartus 下 实现 nios II 试验(未完成啊)
- Java for LeetCode 145 Binary Tree Postorder Traversal
- 【Linux 1.0内核源码剖析】创建进程——fork.c
- C++中 #ifdef 和#endif的作用
- Android-Canvas&Drawable
- 一致性哈希算法解决分布式数据扩容