poj1185 炮兵阵地(状压dp)
2016-07-16 11:52
295 查看
炮兵阵地
Description司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用”H” 表示),也可能是平原(用”P”表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者’H’),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。Output仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。Sample Input5 4
PHPP
PPHH
PPPP
PHPP
PHHPSample Output6
这道题需要自己好好想想,推一推状态方程。
为什么是这样子?
状态方程如下:
int &t=dp[i][l][j];
t=max(t,dp[i-1][j][k]+coun[l]);
为什么是这样?
因为炮的射程有两格,所以我们应该使用三维,第一维表示哪一行,第二维表示第一格射程,第三维表示第二格射程。
所以我们的dp数组应该是dp[101][(1
事实上我开始犯了这样一个错误,我写的是
这样子判断的是j是否在i状态中,这个需要仔细想一下。。。
然后就是代码了:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 24753 | Accepted: 9551 |
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符(‘P’或者’H’),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。Output仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。Sample Input5 4
PHPP
PPHH
PPPP
PHPP
PHHPSample Output6
这道题需要自己好好想想,推一推状态方程。
为什么是这样子?
状态方程如下:
int &t=dp[i][l][j];
t=max(t,dp[i-1][j][k]+coun[l]);
为什么是这样?
因为炮的射程有两格,所以我们应该使用三维,第一维表示哪一行,第二维表示第一格射程,第三维表示第二格射程。
所以我们的dp数组应该是dp[101][(1
if((i&j)^i) return true; return false;`
事实上我开始犯了这样一个错误,我写的是
if((i&j)^j)return true; return false;
这样子判断的是j是否在i状态中,这个需要仔细想一下。。。
然后就是代码了:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #include<vector> #define cls(x,y) memset((x),(y),sizeof((x))); const int maxn=105; const int maxm=15; const int maxk=(1<<10)+1; char a[maxn][maxm]; int dp[maxn][maxn][maxn]; int val[maxn]; int n,m; bool used[maxm]; int nums,coun[maxk],sta[maxk]; bool J(int j) { if(((j<<1)&j)||((j<<2)&j))return false; return true; } bool F(int s,int t) { if(s&t)return false; return true; } bool f(int i,int j) { if((i&j)^i)return true; return false; } void work() { cls(dp,0) nums=0; for(int i=0; i<(1<<m); ++i) { if(!J(i))continue; sta[nums]=i; int t=0,fl=i; while(fl) { ++t; fl&=fl-1; } coun[nums++]=t; } int ans=0; for(int i=0; i<nums; ++i) { // cout<<sta[i]<<" "<<val[1]<<endl; if(f(sta[i],val[1]))continue; // cout<<sta[i]<<" "<<val[1]<<" "<<coun[i]<<endl; int &t=dp[1][i][0]; t=max(t,coun[i]); ans=max(ans,t); } for(int i=2; i<=n; ++i) { for(int j=0; j<nums; ++j) {//force i-1 if(f(sta[j],val[i-1]))continue; for(int k=0; k<nums; ++k) {//force i-2 if((sta[j]&sta[k])||f(sta[k],val[i-2]))continue; for(int l=0; l<nums; ++l) {//force i if((sta[l]&sta[k])||(sta[l]&sta[j])||(f(sta[l],val[i])))continue; int &t=dp[i][l][j]; t=max(t,dp[i-1][j][k]+coun[l]); ans=max(ans,t); } } } } printf("%d\n",ans); } int main() { #ifdef tangge freopen("1185.txt","r",stdin); #endif // tangge while(~scanf("%d%d",&n,&m)) { getchar(); #ifdef tangge if(!n&&!m)break; #endif // tangge for(int i=1; i<=n; ++i)scanf("%s",a[i]); cls(val,0) for(int i=1; i<=n; ++i) { for(int j=0; j<m; ++j) { val[i]=(val[i]<<1)+(a[i][j]=='P'); } } work(); } return 0; }
相关文章推荐
- JavaScriptCore使用
- ionic 中使用pouchdb + sqlite 来实现app的本地存储
- ios修改textField的placeholder的字体颜色、大小
- 史上最全的iOS各种设备信息获取总结
- 编程实现打印出26个字母的所有子集
- JUnit测试【1】(断言)
- android 通知提醒
- Mysql优化实验(一)-- 分区
- LightOJ 1248 Dice (III) 概率
- 关联规则之Apriori
- 银行管理系统
- Spring杂记之--Spring配置文件
- 剑指offer系列—T28字符串的排列
- 数据库清除重复数据
- 在 Perl 中使用 Getopt::Long 模块来接收用户命令行参数
- dp和px间的转换及屏幕宽高的获取
- 移动端click事件延迟300ms正解大全
- 羊驼
- [poj 3461]Oulipo[kmp]
- php数据类型以及判断isset或者empty使用