poj 1185 状态压缩dp(炮兵阵地)
2015-07-26 15:50
453 查看
题意:司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示)。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一个炮兵部队攻击到的区域:沿横向左右各两格,沿纵向上下各两格。炮兵的攻击范围不受地形的影响。 现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
思路:dp[i][j][k]表示第i行布局为j,第i-1行布局为k时,前i行的最多炮兵数目。1、j,k这两种布局必须相容。否则 dp[i][j][k] = 0;2、 dp[i][j][k] = max{dp[i-1][k][m], m = 0...1023} + Num(j),Num(j)为布局j中炮兵的数目,且j和m必须相容。此时满足无后效性。
初始条件:
dp[0][j][0] = Num(j)
dp[1][i][j] = dp[0][j][0] + Num(i);
这样一来需要开100*1024*1024大的数组,不能承受。注意到每一行里最多能放4个炮兵。就算全是平地,能放炮兵的方案数目也不超过 60 (用一遍dfs可以全部求出)。算出一行在全平地情况下所有炮兵的排列方案,存入数组state[65],那么int dp[100][70][70] 足矣。
思路:dp[i][j][k]表示第i行布局为j,第i-1行布局为k时,前i行的最多炮兵数目。1、j,k这两种布局必须相容。否则 dp[i][j][k] = 0;2、 dp[i][j][k] = max{dp[i-1][k][m], m = 0...1023} + Num(j),Num(j)为布局j中炮兵的数目,且j和m必须相容。此时满足无后效性。
初始条件:
dp[0][j][0] = Num(j)
dp[1][i][j] = dp[0][j][0] + Num(i);
这样一来需要开100*1024*1024大的数组,不能承受。注意到每一行里最多能放4个炮兵。就算全是平地,能放炮兵的方案数目也不超过 60 (用一遍dfs可以全部求出)。算出一行在全平地情况下所有炮兵的排列方案,存入数组state[65],那么int dp[100][70][70] 足矣。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 105 #define M 65 int n,m,mm; int state[65],w[65],num = 0; int dp [M][M],t[105]; char s[105][15]; int flag[15]; void dfs(int d){ int i,j = 0,sum=0; if(d == m){ for(i = 0,j=m-1;j>=0;j--){ i <<= 1; if(flag[j] == 1){ i++; sum++; } } state[num] = i; w[num++] = sum; return ; } dfs(d+1); if((d>=2&&!flag[d-1]&&!flag[d-2])||(d==1&&!flag[d-1])||!d){//因为两个大炮之间至少隔两个地方不能放东西 flag[d] = 1; dfs(d+1); flag[d] = 0; } } int main(){ int i,j,k,a,res=0; scanf("%d %d",&n,&m); for(i = 0;i<n;i++) scanf("%s",s[i]); for(i = 0;i<n;i++) for(j = 0;j<m;j++){ t[i] <<= 1; t[i] += (s[i][j]=='P'); } memset(dp, 0, sizeof(dp)); memset(flag,0,sizeof(flag)); dfs(0);//搜索一行中能够成立的所有状态,存入state数组 for(i = 0;i<num;i++) if(!(state[i] & (~t[0]))) dp[0][i][0] = w[i]; for(i = 0;i<num;i++) for(j = 0;j<num;j++) if(!(state[i] & state[j]) && !(state[i] & (~t[1]))) dp[1][i][j] = dp[0][j][0]+w[i]; for(i = 2;i<n;i++) for(j = 0;j<num;j++){ if(state[j] & (~t[i])) continue; for(k = 0;k<num;k++){ if(state[j] & state[k]) continue; for(a = 0;a<num;a++) if(!(state[j]&state[a])) dp[i][j][k] = max(dp[i][j][k],w[j]+dp[i-1][k][a]); } } for(i = 0;i<num;i++) for(j = 0;j<num;j++) res = max(res,dp[n-1][i][j]); printf("%d\n",res); return 0; }
相关文章推荐
- [基本实验] 远程文件包含
- 【SQL Server 2008 使用篇】无法连接到服务器
- 机房收费系统——上下机
- python编码笔记
- bootstrap javascript插件中类成员命名之最前面有无$
- ActiveMQ
- 深入了解MySQL
- 【Treap】【TYVJ 1728】普通平衡树
- ssh中“Host key verification failed.“的解决方案
- 源码编译lnmp(Nginx 1.8 + MySQL5.5 + PHP 5.3)
- Java 内存泄露 与 Reference
- HTML5基础18----HTML5实体
- HTML5基础17----HTML5背景
- 5. php 基本数据类型
- 【java】this()与super()使用详解
- HTML5——Day1
- ActiveMQ学习-Network connectors(1)
- Leetcode|Reverse Words in a String
- iOS中自定义UIImageView用TargetAction模式实现关灯小游戏
- 自己动手(二)──PullToRefresh之上拉翻页(3)