POJ 1185 炮兵阵地 (状态压缩dp)
2016-07-17 22:29
363 查看
这题的状态我是这样定义的:
dp[i][j][k] 表示在第k行前,当前状态是i,上一行的状态是j的时候,最多可以放多少个炮。
一开始我定义的时候,没有中间那个j,但是后来想想似乎不对。
如果这样定义的话,碰到这种情况就不对了。
HPH
PHP
HPH
第三行,按照(错误)定义,是从第二行来的,第二行是从第一行来。
但是这时的第三行和第一行明显不可以同时存在于第二列上。
这样的定义就会算进去,会错误。
所以需要多加一维。
另外这题i,j并不是真正的状态,而是状态集合的下标。
因为通过运算,发现,一行最多只有60种可行情况。
所以数组不需要开到1<<10这样大,只要开比60多就行了。
代码如下:
dp[i][j][k] 表示在第k行前,当前状态是i,上一行的状态是j的时候,最多可以放多少个炮。
一开始我定义的时候,没有中间那个j,但是后来想想似乎不对。
如果这样定义的话,碰到这种情况就不对了。
HPH
PHP
HPH
第三行,按照(错误)定义,是从第二行来的,第二行是从第一行来。
但是这时的第三行和第一行明显不可以同时存在于第二列上。
这样的定义就会算进去,会错误。
所以需要多加一维。
另外这题i,j并不是真正的状态,而是状态集合的下标。
因为通过运算,发现,一行最多只有60种可行情况。
所以数组不需要开到1<<10这样大,只要开比60多就行了。
代码如下:
#include<iostream> #include<string.h> #include<string> #include<stdio.h> using namespace std; char grid[120][12]; int able[100][120]; int pt[120]; int dp[100][100][120]; int n,m; void init() { memset(grid,0,sizeof(grid)); memset(able,0,sizeof(able)); memset(pt,0,sizeof(pt)); memset(dp,0,sizeof(dp)); } bool test1(int now,int row) { for(int i=m-1;i>=0;i--) { if(now%2==1 && grid[row][i]=='H') return false; now=now/2; } return true; } int test2(int S) { return (((S<<1)&S) | ((S<<2)&S)); } int bitcount(int S) { int cnt=0; /*while(S>0) { cnt+=(S&1); S=(S>>1); }*/ while(S>0) { if(S%2==1) cnt++; S=S/2; } return cnt; } int main() { while(cin>>n>>m) { init(); for(int i=0;i<n;i++) { scanf("%s",grid[i]); } for(int i=0;i<n;i++) { for(int S=0;S<(1<<m);S++) { if(test1(S,i)==false) continue; if(test2(S)!=0) continue; able[pt[i]][i]=S; pt[i]++; } } //printf("%d\n",pt[0]); //枚举第一行 for(int i=0;i<pt[0];i++) { int S=able[i][0]; dp[i][0][0]=bitcount(S); } //枚举第二行 for(int i=0;i<pt[1];i++) { int S=able[i][1]; for(int j=0;j<pt[0];j++) { int P=able[j][0]; if( (P&S)!=0 ) continue; dp[i][j][1]=max(dp[i][j][1],dp[j][0][0]+bitcount(S)); } } //正式开始 for(int r=2;r<n;r++) { for(int i=0;i<pt[r];i++) { int S=able[i][r]; for(int j=0;j<pt[r-1];j++) { int P=able[j][r-1]; if((P&S)!=0) continue; for(int k=0;k<pt[r-2];k++) { int T=able[k][r-2]; if((T&S)!=0 || (P&T)!=0) continue; dp[i][j][r]=max(dp[i][j][r],dp[j][k][r-1]+bitcount(S)); } } } } int ans=0; for(int i=0;i<100;i++) { for(int j=0;j<100;j++) { ans=max(ans,dp[i][j][n-1]); } } printf("%d\n",ans); } return 0; }
相关文章推荐
- Dialog
- Python 基础练习01
- 东湖
- jsDOM编程-拖拽层
- C语言的体系结构--main函数存在的必然性(听杨力祥老师的课)
- vi编辑器开发步骤
- SPI详解
- 数据结构(二)非线性结构之二叉树
- 数组中重复的数字 java
- RxJava 与 Retrofit 结合的最佳实践
- css 边框
- C语言的体系结构--main函数存在的必然性(听杨力祥老师的课)
- R绘图学习笔记
- 创建和操作表
- 小波分析资料总结【持续更新】
- 【经典算法】:剑指offer(08)-调整数组顺序使奇数位于偶数前面
- EasyUI之EasyLoader加载器
- iOS性能优化(转载)
- 开博第一文,讲一讲我的进化之路
- EasyUI之EasyLoader加载器