炮兵阵地 POJ - 1185 状压DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Waves___/article/details/74165563

炮兵阵地
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。

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)


扫描二维码关注公众号,回复: 6234676 查看本文章
#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 
*/




猜你喜欢

转载自blog.csdn.net/Waves___/article/details/74165563