题意:中文题……
解法:状压dp。用二进制数表示一行的状态,1表示放人,0表示不放人,考虑dp[i][j][k]表示第i行状态为j,第i-1行状态为k时的人数,则有状态转移方程当状态枚举状态jkl分别表示第i行、第i-1行、第i-2行状态,当jkl互相兼容时,dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + num[j]),num[i]表示状态i中的人数,状态一共有210个,所以复杂度为n×210×210×210,是不可以接受的,但因为每行里人之间的距离至少为2,所以合法的状态只有60,可以深搜得到,这样复杂度变为n×60×60×60。状态i和j兼容的条件为i&j等于0,即没有两个士兵站在同一列上,可以按同样的方法压缩地图的状态。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<iomanip>
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
char maze[110][15];
int state[100];
int tot = 0;
int num[60];
void dfs(int now, int pos, int ni)
{
num[tot] = ni;
state[tot++] = now;
for(int i = pos + 3; i < 10; i++)
{
int tmp = 1 << i;
dfs(now | tmp, i, ni + 1);
}
}
int dp[105][60][60];
int M[105];
int main()
{
dfs(0, -3, 0);
int n, m;
while(~scanf("%d%d", &n, &m))
{
memset(M, 0, sizeof M);
for(int i = 1; i < n + 1; i++)
{
scanf("%s", maze[i]);
for(int j = 0; j < 10; j++)
{
M[i] <<= 1;
if(maze[i][j] != 'P') ++M[i];
}
}
memset(dp, 0, sizeof dp);
for(int i = 1; i < n + 1; i++)
{
for(int j = 0; j < 60; j++)
{
for(int k = 0; k < 60; k++)
{
for(int l = 0; l < 60; l++)
{
if(state[l] & M[i]) continue;
if(state[j] & state[k]) continue;
if(state[j] & state[l]) continue;
if(state[k] & state[l]) continue;
dp[i][l][k] = max(dp[i][l][k], dp[i - 1][k][j] + num[l]);
}
}
}
}
int ans = 0;
for(int i = 0; i < 60; i++)
for(int j = 0; j < 60; j++)
ans = max(dp[n][i][j], ans);
printf("%d\n", ans);
}
return 0;
}