POJ 3254 Corn Fields(状压DP入门)
来源:互联网 发布:浙江省中医院知乎 编辑:程序博客网 时间:2024/05/24 11:15
题意:一个m*n(m, n <= 12)矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,
要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
思路:可以看代码中的注释。转移方程:dp[i][sta] = ∑(dp[i-1][sta']) (sta‘为与sta不冲突的状态)
带注释代码:
#include <cstdio>#include <cstring>using namespace std;#define mod 100000000int M,N,top = 0;//top表示每行最多的状态数int state[600],num[110]; //state存放每行所有的可行状态(即没有相邻的状态//int dp[20][600];//dp[i][j]:对于前i行数据,每行有前j种可能状态时的解int cur[20];//cur[i]表示的是第i行整行的情况inline bool ok(int x){//判断状态x是否可行 if(x&x<<1)return false;//若存在相邻两个格子都为1,则该状态不可行 return true;}void init(){//遍历所有可能的状态 top = 0; int total = 1 << N; //遍历状态的上界 for(int i = 0; i < total; ++i){ if(ok(i))state[++top] = i; }}inline bool fit(int x,int k){ //判断状态x 与第k行的实际状态的逆是否有‘重合’ if(x&cur[k])return false; //若有重合,(即x不符合要求) return true; //若没有,则可行}int main(){ while(scanf("%d%d",&M,&N)!= EOF){ init(); memset(dp,0,sizeof(dp)); for(int i = 1; i <= M; ++i){ cur[i] = 0; int num; for(int j = 1; j <= N; ++j){ //输入时就要按位来存储,cur[i]表示的是第i行整行的情况,每次改变该数字的二进制表示的一位 scanf("%d",&num); //表示第i行第j列的情况(0或1) if(num == 0) //若该格为0 cur[i] +=(1<<(j-1)); //则将该位置为1(注意要以相反方式存储,即1表示不可放牧 } } for(int i = 1;i <= top;i++){ if(fit(state[i],1)){ //判断所有可能状态与第一行的实际状态的逆是否有重合 dp[1][i] = 1; //若第1行的状态与第i种可行状态吻合,则dp[1][i]记为1 } } /* 状态转移过程中,dp[i][k] =Sigma dp[i-1][j] (j为符合条件的所有状态)*/ for(int i = 2; i <= M; ++i){ //i索引第2行到第M行 for(int k = 1; k <= top; ++k){ //该循环针对所有可能的状态,找出一组与第i行相符的state[k] if(!fit(state[k],i))continue; //判断是否符合第i行实际情况 for(int j = 1; j <= top ;++j){ //找到state[k]后,再找一组与第i-1行符合,且与第i行(state[])不冲突的状态state[j] if(!fit(state[j],i-1))continue; //判断是否符合第i-1行实际情况 if(state[k]&state[j])continue; //判断是否与第i行冲突 dp[i][k] = (dp[i][k] +dp[i-1][j])%mod; //若以上皆可通过,则将'j'累加到‘k'上 } } } int ans = 0; for(int i = 1; i <= top; ++i){ //累加最后一行所有可能状态的值,即得最终结果!!!泥马写注释累死我了终于写完了! ans = (ans + dp[M][i])%mod; } printf("%d\n",ans); }}
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn = 13;const int mod = 1e8;int state[1<<maxn], dp[maxn][1<<maxn];int cur[maxn], m, n, top;bool ok(int x){ return !(x&x<<1);}void init(){ top = 0; int total = 1<<n; for(int i = 0; i < total; i++) if(ok(i)) state[top++] = i;}bool fit(int x, int k){ return !(x&cur[k]);}int main(void){ while(cin >> m >> n) { init(); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= m; i++) { cur[i] = 0; int x; for(int j = 1; j <= n; j++) { scanf("%d", &x); if(!x) cur[i] += 1<<(j-1); } } for(int i = 0; i < top; i++) if(fit(state[i], 1)) dp[1][i] = 1; for(int i = 2; i <= m; i++) for(int k = 0; k < top; k++) { if(!fit(state[k], i)) continue; for(int j = 0; j < top; j++) { if(!fit(state[j], i-1)) continue; if(state[k]&state[j]) continue; dp[i][k] = (dp[i][k]+dp[i-1][j])%mod; } } int ans = 0; for(int i = 0; i < top; i++) ans = (ans+dp[m][i])%mod; printf("%d\n", ans); } return 0;}
阅读全文
1 0
- poj 3254 Corn Fields 状压dp入门
- poj 3254 Corn Fields 【状压 DP 入门】
- POJ-3254 Corn Fields 状压dp入门
- poj 3254 Corn Fields--状压dp入门
- POJ 3254 Corn Fields 状压dp入门
- POJ 3254 Corn Fields(状压DP入门)
- poj 3254 Corn Fields 状压dp入门题
- Corn fields poj 3254 (状压dp入门)
- POJ 3254 Corn Fields(状压dp)
- [poj 3254]Corn Fields[状压DP]
- poj 3254 Corn Fields 状压dp
- POJ 3254 Corn Fields 【状压DP】
- Corn Fields - POJ 3254 状压dp
- POJ 3254 Corn Fields 状压DP
- POJ 3254 Corn Fields(状压dp)
- POJ 3254-Corn Fields(状压DP)
- poj 3254 Corn Fields(状压dp)
- POJ 3254 - Corn Fields [状压DP]
- mysql创建时间维度的sql脚本
- Android安装教程
- NALU数据打RTP包流程详解
- springmvc注解(1)
- ruby on rails 合并多个结果集并排序
- POJ 3254 Corn Fields(状压DP入门)
- iOS MDM详解
- Linux---ubuntu下core文件的产生与使用
- gulp自动化构建工具
- 初创企业如何快速实现数据化运营
- 性能测试划分
- 走穿Android动画---补间动画alpha、scale、translate、rotate、set的xml属性及用法
- RecycleView的使用及坑
- 高通ffbm的一些问题随笔记 7 19