[POJ 1185-- artillery-shaped pressure space pretreatment DP & Optimization]

Topic Portal


Description

Command generals intend to deploy their artillery on a grid map of N * M. N * M is a map consisting of N rows and M columns, each cell may be mountain map (indicated by "H"), it may be plain (indicated by "P"), as shown below. Can be arranged on each cell up to a plain terrain artillery (not to deploy artillery on the mountain); a range artillery attack on a map shown in black areas like this:
Here Insert Picture Description
If the gray on the map of identity the deployment of a plain artillery, the figure represents a black grid to a region that can attack: two each along the left and right lateral frame, two cells up and down in the longitudinal direction. The figure was not attack other white grid. Visible effects of artillery attacks against a range of terrain from the map.
Now, the generals were planning how to deploy artillery, under the premise of preventing accidental injury (guarantee not attack each other between any two artillery units, that is, any one artillery unit is not within the scope of the attack other artillery support) throughout the map the maximum number of the army's artillery units can be placed in the area.


Input

The first line contains two positive integers separated by spaces apart, N and M, respectively;
the next N rows, each row comprising M consecutive characters ( 'P' or 'H'), with no spaces. Order data representing a map of each line. N <= 100; M <= 10.


Output

Only one line contains an integer K, represents the number up to the placing of artillery.


Sample Input

5 4
PHPP
PPHH
PPPP
PHPP
PHHP


Sample Output

6


answer

  • First, the data range is easily seen form pressure DP
  • This question and corn fields this question like (click on the link to see the original title & explanations)
  • Since the range of the shells is 2, the state of the two rows enumerate, DP-dimensional array also a need to increase.
  • definition: DP [i] [j] [k]: i-th row when the state j, the maximum number of line status forces when k
  • Plain: 1; Mountain: 0
  • Similarly, what we require pretreatment: When entered, the status of each line converting decimal save up and needs to be recorded in a row, the condition (without any sideways forces two hit each other) state. Note, however, in accordance with the scope of the topic, here is 1 << 10, the array will directly open dp MLE, is in fact due to an attack from the 2, only less than 60 cases.
  • Since this question is seeking the largest number of troops, so when the pre-seeking about the way each state 1 (plain) number
  • State transition equation:DP [i-row] [state j] [on line state k] = max (dp [i] [j] [k], dp [on line: i-1] [state k] on the line [on state t] + number (flat) state j 1);
  • Remember enumeration state of each line, determining whether to allow a subset of the input, and the uplink and downlink for conflicts
  • Finally, you can take the maximum running side

note

  • Still quite satisfactory shaped pressure DP, very simple
  • Remember space needs only 60 can be, or will MLE
  • The first line of the initialization time to consider whether it is a subset of the input

To providing data

1 1
P
1 1
H
12 9
HPHHPHHPH
PPPHHPPHP
HHPHHHHPP
PHHHHPHHP
HHHPHPHHH
HPHPPPPPP
PPPHHPPPP
HPHPHHHPH
PPHPPPHPH
PHPHPPPHP
HPHHPHHPH
HPPPHHPHH


1
0
25


AC-Code

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int mod = 1e9;

int f[101];
int dp[101][70][70]; // 第 i 行,状态为 j,i-1行状态为 k 时候的最大价值
int state[70];
int num[70];	// 每种状态 1 的个数
int cnt;
int main() {
	ios;
	int n, m;

	while (cin >> n >> m) {
		cnt = 0;
		memset(dp, 0, sizeof(dp));
		for (int i = 0; i < 1 << m; ++i) {
			if (!(i & i << 2) && !(i & i << 1))
				state[cnt] = i;
			else
				continue;
			int j = 0;
			int temp = i;
			for (j = 0; temp; ++j)
				temp &= (temp - 1); // 去掉最低位的 1
			num[cnt++] = j;

		}
		for (int i = 1; i <= n; ++i) {
			string str;
			cin >> str;
			int sum = 0;
			for (int j = 0; j < m; ++j) {
				if (str[j] == 'P')	// 1 :平原, 0 :山
					sum = sum << 1 | 1;
				else
					sum = sum << 1;
			}
			f[i] = sum;
		}

		for (int i = 0; i < cnt; i++) {
			if (!(state[i] & f[1]))	continue;
			dp[1][i][0] = num[i]; // 第 1 行初始化
		}
		for (int i = 2; i <= n; ++i) { // 第 i 行
			for (int j = 0; j < cnt; ++j) { // 枚举当前行状态 j
				if ((state[j] & f[i]) == state[j]) {
					for (int k = 0; k < cnt; ++k) { // 枚举上一行状态
						if ((state[k] & f[i - 1]) == state[k] && !(state[j] & state[k]))
							for (int t = 0; t < cnt; ++t) {
								if ((state[t] & f[i - 2]) == state[t] && !(state[j] & state[t]) && !(state[k] & state[t]))
									dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][t] + num[j]);
							}

					}
				}
			}
		}
		int ans = 0;
		for (int i = 0; i < cnt; ++i) {
			for (int j = 0; j < cnt; ++j) {
				ans = max(ans, dp[n][i][j]);
			}
		}
		cout << ans << endl;
	}
}


Published 104 original articles · won praise 60 · views 5851

Guess you like

Origin blog.csdn.net/Q_1849805767/article/details/103590031