和炮兵阵地如出一辙,但还是半天才改出来,麻烦就麻烦在测试数据不好找,错也不知道错哪了。。。
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
using namespace std;
const int N = 200;
const int INF = 1e8;
const int mod = 100000000;
int n, m, top, total;
int state[N], cur[110], dp[110][N][N], num[N];
bool ok(int x)
{
if(x & (x >> 2)) return false;
if(x & (x << 2)) return false;
else return true;
}
void init()
{
top = 0;
total = 1 << m;
for(int i = 0; i < total; i ++)
{
if(ok(i)) state[++ top] = i;
}
}
bool fit(int x, int y)
{
if(x & y) return false;
else return true;
}
int jcount(int x)
{
int cnt = 0;
while(x)
{
cnt ++;
x &= (x - 1);
}
return cnt;
}
int main()
{
// freopen("in.txt", "r", stdin);
int num0;
while(~scanf("%d%d", &n, &m))
{
memset(dp, -1, sizeof(dp));
init();
//输入,同时记录该行的状态
for(int i = 1; i <= n; i ++)
{
cur[i] = 0;
for(int j = 1; j <= m; j ++)
{
cin >> num0;
if(num0 == 0) cur[i] += (1 << (j - 1));
}
}
//初始化第一行
for(int i = 1; i <= top; i ++)
{
num[i] = jcount(state[i]);
if(fit(state[i], cur[1])) dp[1][1][i] = num[i];
}
//分层dp
for(int i = 2; i <= n; i ++)
{
for(int t = 1; t <= top; t ++)//当前行
{
if(!fit(state[t], cur[i])) continue;
for(int k = 1; k <= top; k ++)//上一行
{
if(!fit(state[k], cur[i - 1])) continue;
if((state[t] & (state[k] << 1)) || (state[t] & (state[k] >> 1))) continue;
for(int j = 1; j <= top; j ++) //上上行
{
if(!fit(state[j], cur[i - 2])) continue;
if(state[t] & state[j]) continue;
if(dp[i - 1][j][k] == -1) continue;
if((state[k] & (state[j] << 1)) || (state[k] & (state[j] >> 1))) continue;
dp[i][k][t] = max(dp[i][k][t], dp[i - 1][j][k] + num[t]);
}
}
}
}
//输出
int ans = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= top; j ++)
for(int k = 1; k <= top; k ++)
ans = max(ans, dp[i][j][k]);
printf("%d\n", ans);
}
return 0;
}