炮兵阵地
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 27960 | Accepted: 10821 |
Description
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。
现在,将军们规划如何部署炮兵部队,在防止误伤的前提下(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多能够摆放多少我军的炮兵部队。
Input
第一行包含两个由空格分割开的正整数,分别表示N和M;
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
接下来的N行,每一行含有连续的M个字符('P'或者'H'),中间没有空格。按顺序表示地图中每一行的数据。N <= 100;M <= 10。
Output
仅一行,包含一个整数K,表示最多能摆放的炮兵部队的数量。
Sample Input
5 4 PHPP PPHH PPPP PHPP PHHP
Sample Output
6
Source
题目链接:http://poj.org/problem?id=1185
题目:在一个N*M的矩阵上布置炮兵部队,P为平原,H为山地,只有平原可以布置炮兵部队,
然后每个炮兵部队都有一个攻击范围,它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。
问:如何部署炮兵部队,在防止误伤的前提下
(保证任何两支炮兵部队之间不能互相攻击,即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内),
在整个地图区域内最多能够摆放多少我军的炮兵部队?
Corn Fields POJ - 3254 的升级版
预处理合法状态state[],并计算每个合法状态中1的个数num[]
dp[i][s1][s2] 表示当前行状态为s1,上一行状态为s2的最多炮兵数
dp[i][s1][s2] = max{ dp[i][s1][s2], num[s] + dp[i - 1][s2][s3] }
其中当前行状态为s1, 上一行状态为s2,上上行状态为s3,且 s1,s2,s3互相兼容 且都与地图兼容
这里我滚动了数组,因此
dp[z][s1][s2] = max{ dp[z][s1][s2], num[s] + dp[1 - z][s2][s3] }
(z = i % 2)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 1e18
using namespace std;
typedef pair<int, int> P;
const int maxn = 2e5 + 5;
const int mod = 1e8;
int dp[2][65][65];
int state[65], cnt, num[65];
int mp[105];
int n, m;
int main(void)
{
// std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// freopen("in.txt", "r", stdin);
char ch;
while (~scanf("%d %d", &n, &m)){
cnt = 0;
memset(state, 0, sizeof state);
memset(num, 0, sizeof num);
for (int s = 0; s < (1 << m); s++){
if (s & (s << 1)) continue;
if (s & (s << 2)) continue;
state[++cnt] = s;
for (int i = 0; i < m; i++)
if (s & (1 << i)) num[cnt]++;
}
memset(dp, 0, sizeof dp);
memset(mp, 0, sizeof mp);
for (int i = 1; i <= n; i++){
getchar();
for (int j = 1; j <= m; j++){
scanf("%c", &ch);
if (ch == 'H') mp[i] += (1 << (j-1)); // H位置赋值1,P位置赋值0,方便位运算
}
}
for (int s = 1; s <= cnt; s++){ // 第1行
if (!(mp[1] & state[s])) dp[1][s][1] = num[s];
}
// 滚动数组,注意当 n==1
for (int s = 1; s <= cnt; s++){ // 第2行
if (mp[2] & state[s]) continue;
for (int k = 1; k <= cnt; k++){
if (mp[1] & state[k]) continue;
if (state[s] & state[k]) continue;
dp[0][s][k] = max(dp[0][s][k], num[s] + dp[1][k][1]);
}
}
int z = 0;
for (int i = 3; i <= n; i++){
z = i % 2;
memset(dp[z], 0, sizeof dp[z]);
for (int s1 = 1; s1 <= cnt; s1++){
if (mp[i] & state[s1]) continue; // 状态s1与地图兼容
for (int s2 = 1; s2 <= cnt; s2++){
if (mp[i - 1] & state[s2]) continue; // 状态s2与地图兼容
if (state[s1] & state[s2]) continue; // 状态s1与s2兼容
for (int s3 = 1; s3 <= cnt; s3++){
if (mp[i - 2] & state[s3]) continue; // 状态s3与地图兼容
if (state[s1] & state[s3]) continue; // 状态s1与s3兼容
if (state[s2] & state[s3]) continue; // 状态s2与s3兼容
dp[z][s1][s2] = max(dp[z][s1][s2], num[s1] + dp[1 - z][s2][s3]);
}
}
}
}
int ans = -1;
for (int s = 1; s <= cnt; s++)
for (int k = 1; k <= cnt; k++)
ans = max(ans, dp[n % 2][s][k]);
// ans = max(ans, dp[z][s][k]); 当 n==1,这样就写wa了,看了半天。。。
cout << ans << endl;
}
return 0;
}
/*
5 4
PHPP
PPHH
PPPP
PHPP
PHHP
6
*/