POJ 1185 炮兵阵地(状态压缩DP)
2016-05-18 07:54
507 查看
B - 炮兵阵地
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d
& %I64u
Submit Status
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
![](http://7xjob4.com1.z0.glb.clouddn.com/ba1d4fa736b99550a7ee43784c287df9)
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
Sample Output
题解:nState为状态数,state数组为可能的状态
代码:
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d
& %I64u
Submit Status
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
题解:nState为状态数,state数组为可能的状态
代码:
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <string> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; typedef long long ll; typedef unsigned long long ull; #define fi first #define se second #define prN printf("\n") #define SI(N) scanf("%d",&(N)) #define SII(N,M) scanf("%d%d",&(N),&(M)) #define SIII(N,M,K) scanf("%d%d%d",&(N),&(M),&(K)) #define cle(a,val) memset(a,(val),sizeof(a)) #define rep(i,b) for(int i=0;i<(b);i++) #define Rep(i,a,b) for(int i=(a);i<=(b);i++) int n,m,dp[105][80][80]; int row[105]; int nState,state[80],num[80]; void init() { int k=1<<m; nState=0; rep(i,k) { if ((i&(i<<1))==0&&(i&(i<<2))==0) { state[nState]=i; num[nState]=0; int j=i; while(j) { num[nState]+=j%2; j/=2; } nState++; } } } int main() { #ifndef ONLINE_JUDGE freopen("C:\\Users\\Zmy\\Desktop\\in.txt","r",stdin); // freopen("C:\\Users\\Zmy\\Desktop\\out.txt","w",stdout); #endif // ONLINE_JUDGE char str[20]= {0}; while(cin>>n>>m) { init(); rep(i,n) { row[i]=0; scanf("%s",str); rep(j,m) { if (str[j]=='P') { row[i]+=1<<j; } } } cle(dp,0); rep(j,nState) { if ((state[j]&row[0])!=state[j]) { continue; } rep(k,nState) { dp[0][j][k]=num[j]; } } if (n>1) rep(j,nState) { if ((state[j]&row[1])!=state[j]) { continue; } rep(k,nState)//这的k代表的是上上个 { if ((state[j]&state[k])==0) { dp[1][j][k]=dp[0][k][0] + num[j];/**< 这是啥意思?? */ } } } Rep(i,2,n-1) { rep(j,nState) { if ((state[j]&row[i])!=state[j]) { continue; } rep(k,nState)//这的k代表的是上上个 { if ( state[j] & state[k] ) continue; for (int h = 0; h < nState; h++)/**< i是这个,j是上1,k是上2,h是上3 */ { if ( state[j] & state[h] ) continue; if ( dp[i-1][k][h] > dp[i][j][k] ) dp[i][j][k] = dp[i-1][k][h]; } dp[i][j][k] += num[j]; } } } int maxa = 0; for (int j = 0; j < nState; j++) { for (int k = 0; k < nState; k++) if (maxa < dp[n-1][j][k]) maxa = dp[n-1][j][k]; } printf("%d\n", maxa); } return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- ACM题库以及培养策略