poj 1753 Flip Game
这个题是一道枚举题;这个题最多只要翻转16,因为我们知道一个棋子翻转2次就到了原来的样子,有些人就会问我翻转了他的周围棋子再去翻转他一次,应该又改变了,其实不是的,因为我们在翻转时,我们原来的那一次并没用,因为都是由周围的翻转所影响的;因此,最多只能翻转16次,也就是每个棋子只有翻转与不翻转的这两种情况及(0/1);
下面我们来讲一下策略;如果我们想把第一行翻转成白色,那么第一行黑色的棋子的下方一定受影响;因此第二行受第一行的约束,因此第三、四行也受约束;因此我们可以一行行的暴力过去;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<vector> using namespace std; int d[5][2] = { 0,1,1,0,0,-1,-1,0,0,0 }; bool visit[4][4],flag; int step; bool Judge( int x, int y ) { if( x >=0 && x <=3 && y >=0 && y<=3 ) return true; else return false; } void Opt( bool map[][4], int x , int y ) { int dx ,dy; for( int i = 0 ; i < 5 ; i ++ ) { dx = x + d[i][0] ; dy = y + d[i][1]; if( Judge( dx ,dy ) ) { map[dx][dy] = !map[dx][dy]; } } } bool Judge_all( bool map[][4] ) { for( int i = 0; i <= 3 ; i ++ ) { for( int j = 0; j <= 3 ; j++ ) { if( map[i][j] != map[0][0] ) return false; } } return true; } void DFS( bool map[][4] , int x, int y, int n ) { if( n == step ) { flag = Judge_all( map ); return ; } if( flag || x == 4 ) return; Opt( map , x, y ); if( y < 3 ) DFS( map , x , y + 1 , n + 1 ); else DFS( map , x +1 , 0 , n +1 ); Opt( map , x , y ); if( y < 3 ) DFS( map , x , y + 1 , n ); else DFS( map , x +1 , 0 , n ); } int main( ) { bool map[4][4]; char c[4][4]; while(scanf( "%s",c[0] )==1 ) { flag = 0 ; for( int i = 1 ; i <= 3 ; i ++ ) { scanf( "%s",c[i] ); } for( int i = 0 ; i <= 3 ; i ++ ) { for( int j = 0 ; j <= 3 ; j ++ ) { if( c[i][j] =='b' ) map[i][j] = 0; else map[i][j] = 1; visit[i][j] = false; } } for( step = 0 ; step <= 16 ; step++ ) { DFS( map ,0 , 0, 0); if( flag ) break; } if( !flag ) printf( "Impossible\n" ); else printf( "%d\n",step ); } //system( "pause" ); return 0; }