题意:
n*m的地图(n<=100, m<=10),有H山地、P平原两种地形,平原上可以部署炮兵。炮兵伤害范围为横竖范围2格并且无视地形,问在保证互不伤害的情况下最多部署几个炮兵。
老套路按行转移,炮兵伤害2格,当前行会受到前两行的影响,因此要用到三维,但三维时间空间都炸了。
考虑到炮兵互不伤害,
210
中有很多非法状态,没必要开这么大,预处理出一行的所有可能部署情况,只有60个。每次枚举60个和地形做比较,合法的在进行转移。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int a[110];
int dp[110][63][63];
int num[63], mp[63];
void init()
{
int cnt = 0;
for(int i = 0; i < 1<<10; i++)
{
num[cnt] = 0;
int t = i;
int pre = -3;
int no = 0;
bool flag = true;
while(t)
{
if(t&1)
{
if(no-pre <= 2)
{
flag = false;
break;
}
else
{
pre = no;
num[cnt]++;
}
}
no++;
t >>= 1;
}
if(flag)
mp[cnt++] = i;
}
}
int main()
{
int n, m;
init();
while(~scanf("%d%d", &n, &m))
{
char s[13];
for(int i = 1; i <= n; i++)
{
scanf("%s", s);
a[i] = 0;
for(int j = 1; j <= m; j++)
a[i] = a[i] << 1 | (s[j-1]=='H'?1:0);
}
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++)
for(int j = 0; j < 60; j++)
{
if(mp[j] >= 1<<m || a[i]&mp[j])
continue;
for(int k = 0; k < 60; k++)
{
if(mp[k] >= 1<<m || a[i-1]&mp[k] || mp[k]&mp[j])
continue;
for(int v = 0; v < 60; v++)
{
if(v >= 1<<m || i>=2&&a[i-2]&mp[v] || mp[v]&mp[k] || mp[v]&mp[j])
continue;
dp[i][j][k] = max(dp[i-1][k][v]+num[j], dp[i][j][k]);
}
}
}
int ans = 0;
for(int i = 0; i < 60; i++)
for(int j = 0; j < 60; j++)
ans = max(ans, dp[n][i][j]);
printf("%d\n", ans);
}
return 0;
}