这题开始直接状态压缩每行 2^M 然后就TLE了。。。。
最后看了下别人的发现其实每行的状态没有这么多,因为相邻两个大炮的距离不能小于2 所以当M为10 的时候每行的状态只有60种,每次在得到M的时候,直接搜出这些状态保存起来,然后就可以了。。。。
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int N, M;
int st[100], num[100], tot;
int dp[2][100][100];
char maps[100][10];
void getstatu( int statu, int pos, int sum ){
if( pos >= M ){
num[tot] = sum;
st[tot++] = statu;
return;
}
getstatu( statu, pos + 1, sum );
getstatu( statu | ( 1 << pos ), pos + 3, sum + 1 );
}
bool judge( int r, int now, int pre1, int pre2 ){
for( int i = 0; i < M; i++ ){
if( st[now] & ( 1 << i ) ){
if( maps[r][i] == 'H' || st[pre1] & ( 1 << i ) || st[pre2] & ( 1 << i ) ){
return false;
}
}
}
return true;
}
int main(){
while( scanf( "%d%d", &N, &M ) != EOF ){
for( int i = 0; i < N; i++ ){
scanf( "%s", maps[i] );
}
tot = 0;
getstatu( 0, 0, 0 );
memset( dp, -1, sizeof( dp ) );
int now = 0;
dp[now][0][0] = 0;
for( int i = 0; i < N; i++ ){
now ^= 1;
memset( dp[now], -1, 100 * 100 * sizeof( int ) );
for( int j = 0; j < tot; j++ ){
for( int k = 0; k < tot; k++ ){
if( dp[now^1][j][k] != -1 ){
for( int l = 0; l < tot; l++ ){
if( judge( i, l, j, k ) ){
dp[now][l][j] = max( dp[now][l][j], dp[now^1][j][k] + num[l] );
}
}
}
}
}
}
int ans = 0;
for( int i = 0; i < tot; i++ ){
for( int j = 0; j < tot; j++ ){
ans = max( ans, dp[now][i][j] );
}
}
cout << ans << endl;
}
return 0;
}