题目链接:http://poj.org/problem?id=1185
本题为NOI2001 真题。
题解:
我们先通过预处理(dfs)求出第 i 行的方案数以及方案。
然后判断行、列是否冲突就可以了。
P.S:注意位运算的顺序!被坑了1+h。。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 1 << 26;
int f[105][105][105], h[105][105], g[105][105], d[105];
char s[105][105];
int n, m;
int tot = 0, ans = 0, sum = 0;
void dfs(int x, int i) {
if(x >= m) { //
d[i] = ++tot;
h[i][tot] = ans; // 方案数
g[i][tot] = sum; // 状态
return ;
}
if(s[i][x] == 'P') {
sum += 1 << x;
ans ++;
dfs(x+3, i);
ans --;
sum -= 1 << x;
}
dfs(x+1, i);
}
int main(){
scanf("%d %d", &n, &m);
for ( int i = 1; i <= n; i ++ ) scanf("%s", s[i]);
for ( int i = 1; i <= n; i ++ ) {
ans = sum = tot = 0;
dfs(0, i);
}
for ( int i = 1; i <= d[2]; i ++ ) {
for ( int j = 1; j <= d[1]; j ++ ) {
if((g[2][i]&g[1][j]) == 0) {
f[2][i][j] = h[2][i]+h[1][j];
}
}
}
for ( int i = 3; i <= n; i ++ ) {
for ( int j = 1; j <= d[i]; j ++ ) {
for ( int k = 1; k <= d[i-1]; k ++ ) {
for (int l = 1; l <= d[i-2]; l ++ ) {
if((g[i][j]&g[i-1][k]) == 0 && (g[i][j]&g[i-2][l]) == 0 && (g[i-1][k]&g[i-2][l]) == 0) {
f[i][j][k] = max(f[i][j][k], f[i-1][k][l]+h[i][j]);
}
}
}
}
}
int ans = -1;
if( n == 1 ) {
for ( int i = 1; i <= d[n]; i ++ ) {
ans = max(ans, h[1][i]);
}
} else {
for ( int i = 1; i <= d[n]; i ++ ) {
for ( int j = 1; j <= d[n-1]; j ++ ) {
ans = max(ans, f[n][i][j]);
}
}
}
printf("%d\n", ans);
return 0;
}
/*
3 4
PHPP
PPHH
PPPP
*/