黑书上的题,很好想
dp【0】【i】【j】表示i通过顺时针能否和j相遇
dp【1】【i】【j】表示i通过逆时针能否和j相遇
然后 每次只要枚举i和j之间的状态来转移就可以了
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
int beat[50][50];
int dp[2][50][50];
int N;
int DFS( int statu, int pos1, int pos2 ){
if( statu == 0 && ( pos1 + 1 ) % N == pos2 ){
return 1;
}
if( statu == 1 && ( pos1 + N - 1 ) % N == pos2 ){
return 1;
}
if( dp[statu][pos1][pos2] != -1 ){
return dp[statu][pos1][pos2];
}
int ans = 0;
if( statu == 0 ){
for( int i = ( pos1 + 1 ) % N; i != pos2; i = ( i + 1 ) % N ){
if( DFS( statu, pos1, i ) && DFS( statu, i, pos2 ) && ( beat[pos1][i] || beat[pos2][i] ) ){
ans = 1;
break;
}
}
}else{
for( int i = ( pos1 + N - 1 ) % N; i != pos2; i = ( i + N - 1 ) % N ){
if( DFS( statu, pos1, i ) && DFS( statu, i, pos2 ) && ( beat[pos1][i] || beat[pos2][i] ) ){
ans = 1;
break;
}
}
}
return dp[statu][pos1][pos2] = ans;
}
int main(){
int T;
scanf( "%d", &T );
while( T-- ){
memset( dp, -1, sizeof( dp ) );
scanf( "%d", &N );
for( int i = 0; i < N; i++ ){
for( int j = 0; j < N; j++ ){
scanf( "%d", &beat[i][j] );
}
}
for( int i = 0; i < N; i++ ){
int flag = 0;
for( int j = 0; j < N; j++ ){
if( i != j ){
if( DFS( 0, i, j ) && DFS( 1, i, j ) && beat[i][j] ){
flag = 1;
break;
}
}
}
cout << flag << endl;
}
cout << endl;
}
return 0;
}