样例未过,但我找不到逻辑哪里错了,代码如下:
#include <bits/stdc++.h>
using namespace std;
int T;
int n, m, w[7][7];
int f[7][1 << 6]; // f[j][s]表示取前 i 行的数,且当前行状态为 s 的最大收益
int F[7][1 << 6]; // F[i][s]表示该行当前状态的收益总和
int ans = -1000000;
// 检查跨行冲突
bool check(int s, int l)
{
if (s & l)
return 0; // 正上方冲突
if (s & (l << 1))
return 0; // 左上角冲突
if (s & (l >> 1))
return 0; // 右上角冲突
return 1;
}
int main()
{
ans = -1000000;
memset(F, 0, sizeof(F));
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
scanf("%d", &w[i][j]);
}
}
// 总状态数
int N = (1 << m) - 1;
// 预处理
for (int i = 1; i <= n; i++)
{
for (int s = 0; s <= N; s++)
{
// 检查行内冲突
if (s & (s << 1))
continue;
for (int j = 0; j < m; j++)
{
if ((s >> j) & 1)
{
F[i][s] += w[i][j + 1];
}
}
}
}
// 初始化
memset(f, -127, sizeof(f));
for (int s = 0; s <= N; s++)
{
// 检查行内冲突
if (s & (s << 1))
continue;
f[1][s] = F[1][s];
ans = max(f[1][s], ans);
}
// dp
for (int i = 2; i <= n; i++)
{
for (int s = 0; s <= N; s++)
{
if (s & (s << 1))
continue;
for (int l = 0; l <= N; l++)
{
if (l & (l << 1))
continue;
if (!check(s, l))
continue;
f[i][s] = max(f[i][s], f[i - 1][l] + F[i][s]);
}
ans = max(f[i][s], ans);
}
}
printf("%d\n", ans);
}
return 0;
}
自认为马蜂良好