poj -1185 炮兵阵地 (经典状压dp)
2015-08-10 11:35
309 查看
http://poj.org/problem?id=1185
参考博客:http://poj.org/problem?id=1185
大神博客已经讲的很清楚了,注意存状态的时候是从1开始的,所以初始化的时候也是dp[1][1][state],从0开始的话,状态就是dp[1][0][state]了.
dp[i][j][k]表示第i行状态为k第i-1行状态为j时的方案数.
dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+num[k]); (num[k]为k状态中1的个数)
边界条件:dp[1][1][i]=num[i],状态i可以满足第一行的条件。
还有就是为什么每一行最多只有60种状态,poj题目讨论里面有人给出了枚举的代码。
参考博客:http://poj.org/problem?id=1185
大神博客已经讲的很清楚了,注意存状态的时候是从1开始的,所以初始化的时候也是dp[1][1][state],从0开始的话,状态就是dp[1][0][state]了.
dp[i][j][k]表示第i行状态为k第i-1行状态为j时的方案数.
dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+num[k]); (num[k]为k状态中1的个数)
边界条件:dp[1][1][i]=num[i],状态i可以满足第一行的条件。
还有就是为什么每一行最多只有60种状态,poj题目讨论里面有人给出了枚举的代码。
#include <iostream> using namespace std; bool isok( int c ) { return !(c&(c<<1)||c&(c<<2));//同一行中不能有相邻的1距离小于3 } int main() { int count=0; for( int i=0; i<1024; i++ ) count += isok(i); cout<<count<<endl; return 0; }
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <string> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> //#include <map> #include <queue> #include <deque> //#pragma comment(linker, "/STACK:102400000,102400000") #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define INF 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("a.txt", "r", stdin) #define Write() freopen("b.txt", "w", stdout); #define maxn 110 #define maxv 5010 #define mod 1000000000 using namespace std; int n,m; char map[110][20],num[110],top; int stk[70],cur[110]; int dp[110][70][70]; inline bool ok(int x) //判断该状态是否合法,即同一行不存在相邻1之间的距离小于3的 { if(x&(x<<1)||x&(x<<2)) return 0; return 1; } inline void jnite() //找到所有可能合法的状态 { top=0; int total=1<<m; for(int i=0;i<total;i++) if(ok(i)) stk[++top]=i; } inline bool fit(int x,int k) //判断状态x是否与第k行匹配 { if(cur[k]&x) return 0; return 1; } inline int jcount(int x) //计算一个整型数x的二进制中1的个数(用于初始化) { int cnt=0; while(x) { cnt++; x&=(x-1); //很精炼,每次都会与掉一个1 } return cnt; } int main() { //Read(); while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; jnite(); for(int i=1;i<=n;i++) scanf("%s",map[i]+1); for(int i=1;i<=n;i++) { cur[i]=0; for(int j=1;j<=m;j++) { if(map[i][j]=='H') cur[i]+=(1<<(j-1)); } //printf("%d\n",cur[i]); } memset(dp,0,sizeof(dp)); for(int i=1;i<=top;i++) //初始化第一行 { num[i]=jcount(stk[i]); //printf("%d\n",num[i]); if(fit(stk[i],1)) dp[1][1][i]=num[i]; } for(int i=2;i<=n;i++) { for(int t=1;t<=top;t++) { if(!fit(stk[t],i)) continue;//第i行是否冲突 for(int j=1;j<=top;j++) { if(stk[t]&stk[j]) continue;//第i行和第i-2行是否冲突 for(int k=1;k<=top;k++) { if(stk[t]&stk[k]) continue;//第i行和第i-1行是否冲突 dp[i][k][t]=max(dp[i][k][t],dp[i-1][j][k]+num[t]); // printf("%d\n",dp[i][k][t]); } } } } int ans=0; //得到最大值 for(int i=1;i<=top;i++) for(int j=1;j<=top;j++) ans=max(ans,dp [i][j]); printf("%d\n",ans); } return 0; }
相关文章推荐
- poj-1458 Common Subsequence
- dfs.datanode.max.xcievers&dfs.datanode.max.transfer.threads介绍
- 既可以滑动也可以点击切换(ViewPager跟Fragment)
- HDU 1496 Equations
- HDU 1827 强连通 缩点 Summer Holiday
- 华为OJ(找出字符串中第一个只出现一次的字符)
- hdu4813 Hard Code
- Android 进入后台触发的事件,一般用于APP屏幕解锁
- 这个月需要做什么?
- android 自定义ProgressBar
- 黑马程序员——注解
- 什么是SysWow64
- 编译android5.0源码的
- Ajax--跨域访问的三种方法
- jQuery解决input超多的表单提交
- 最大流dinic模板
- Eclipse抛出GC overhead limit exceeded异常问题的分析与解决
- python yield使用技巧
- Wireless Network
- 求一个数组中超过数组长度一半的元素