按行来递推
在递推的过程中每一行的状态与前两行的状态有关,所以要记录上两行的状态,然后用上两行的状态搜出所有可能的新的两行的状态
和那个炮兵阵地是一样的
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
__int64 dp[2][11][1<<8][1<<8];
char maps[10][10];
int N;
int now, pre;
int ttt[10];
int nowi;
void DFS( int pos, int num, int st1, int st2, int cnt ){
if( pos >= 8 ){
int new_st = 0;
for( int i = 0; i < 8; i++ ){
if( ttt[i] == 1 ){
new_st |= ( 1 << i );
}
}
dp[now][num][new_st][st1] += cnt;
return;
}
ttt[pos] = 0;
DFS( pos + 1, num, st1, st2, cnt );
if( num > 0 && maps[nowi][pos] != '*' && !( ( ( st2 & (1<<(pos-1)) ) && pos >= 1 ) || ( ( st2 & (1<<(pos+1)) ) && pos < 7 ) )
&& !( ( ( st1 & (1<<(pos-2)) ) && pos >= 2 ) || ( ( st1 & (1<<(pos+2)) ) && pos < 6 ) ) ){
ttt[pos] = 1;
DFS( pos + 1, num - 1, st1, st2, cnt );
ttt[pos] = 0;
}
}
int main(){
int T;
scanf( "%d", &T );
while( T-- ){
scanf( "%d", &N );
for( int i = 0; i < 8; i++ ){
scanf( "%s", maps[i] );
}
now = 0, pre = 1;
memset( dp, 0, sizeof( dp ) );
dp[now][N][0][0] = 1;
for( int i = 0; i < 8; i++ ){
nowi = i;
swap( now, pre );
memset( dp[now], 0, sizeof( dp[now] ) );
for( int j = 0; j <= N; j++ ){
for( int k = 0; k < ( 1 << 8 ); k++ ){
for( int l = 0; l < ( 1 << 8 ); l++ ){
if( dp[pre][j][k][l] != 0 ){
DFS( 0, j, k, l, dp[pre][j][k][l] );
}
}
}
}
}
__int64 ans = 0;
for( int i = 0; i < ( 1 << 8 ); i++ ){
for( int j = 0; j < ( 1 << 8 ); j++ ){
ans += dp[now][0][i][j];
}
}
printf( "%I64d\n", ans );
}
return 0;
}