トピック:
解像度:
非侵略として
複数のグリッドである
と(F [I] [J \ ] [K] \) i番目の行、列状態を表し\(J \) 、アップリンク状態\を(K \)の最もあなたが大砲を置くことができますが
見つかった\(\ 100倍の1024倍\ 1024 \) 劣ら開けないように
、あるいは簡単な検索で見つかった\(m個== 10 \)法的地位た場合にのみ\(60 \)種
\(100 \回60 \回60 \) 、問題はない
次いで非侵略としては、状態を挙げることができる
状態遷移
(\をF [I] [J ] [K] = maxの\ {F [I] [J] [K]、F [I-1] [K] [L] + SUM [状態[I] \} \)
\(SUM [I]が\)を表し\(私は\)どのように多くの状態\(1 \)
コード:
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m, num, ans = -0x3f3f3f3f;
int state[N], sum[1050], line[N], f[N][N][N];
char s[N];
int qpow(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = ans * a;
a *= a, b >>= 1;
}
return ans;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> s;
for (int j = m - 1; j >= 0; --j)
if (s[j] == 'P') line[i] += qpow(2, m - j - 1);
}
for (int i = 0; i < (1 << m); ++i) {
if ((i & (i << 1)) || (i & (i >> 1)) ||
(i & (i << 2)) || (i & (i >> 2))) continue;
state[++num] = i;
sum[i] = __builtin_popcount(i);
}
for (int i = 1; i <= num; ++i)
if ((state[i] | line[1]) == line[1])
f[1][i][1] = sum[state[i]];
for (int i = 2; i <= n; ++i)
for (int j = 1; j <= num; ++j)
if ((state[j] | line[i]) == line[i])
for (int k = 1; k <= num; ++k)
if ((state[k] | line[i - 1]) == line[i - 1] && !(state[j] & state[k]))
for (int l = 1; l <= num; ++l)
if (!(state[l] & state[k]) &&
!(state[l] & state[j]) &&
(state[l] | line[i - 2]) == line[i - 2])
f[i][j][k] = max(f[i][j][k], f[i - 1][k][l] + sum[state[j]]);
for (int i = 1; i <= num; ++i)
for (int j = 1; j <= num; ++j)
ans = max(ans, f[n][i][j]);
cout << ans;
}