題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1647
題意:
在一個n*m(1 <= n,m <= 15)的棋盤上,每一個格子裡都有一個可以翻轉的棋子。
棋子的一面是黑色,一面是白色。
若翻轉一個棋子,則它周圍的四個棋子也會被翻轉。
問你最少需要多少次翻轉,使所有的棋子都變成白麵向上。
如果可以做到,輸出字典序最小的結果(將結果當成字串處理)。如果不能做到,輸出“IMPOSSIBLE”。
題解:
首先有一個結論:
如果第i-1行第j列的棋子為黑,那麼第i行j列的棋子一定會被翻轉,因為只有這樣上一行的黑棋子才能變成白棋子。
所以,如果上一行的棋子狀態已經確定,那麼當前行的翻轉方案是唯一確定的。
因此,如果第1行的棋子狀態確定,接下來2到n行的方案也都唯一確定了。
所以只用列舉第1行的棋子狀態,複雜度O(2^15)。
注:如果用狀態壓縮state列舉表示第一行的狀態的話,state的第0位代表棋盤的第m-1列。
因為要按字典序從小到大列舉。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 20 5 #define INF 10000000 6 7 using namespace std; 8 9 const int dx[]={-1,1,0,0}; 10 const int dy[]={0,0,-1,1}; 11 12 int n,m; 13 int a[MAX_N][MAX_N]; 14 int t[MAX_N][MAX_N]; 15 int cnt[MAX_N][MAX_N]; 16 int ans[MAX_N][MAX_N]; 17 bool failed=false; 18 19 void read() 20 { 21 cin>>n>>m; 22 for(int i=0;i<n;i++) 23 { 24 for(int j=0;j<m;j++) 25 { 26 cin>>a[i][j]; 27 } 28 } 29 } 30 31 inline bool is_legal(int x,int y) 32 { 33 return x>=0 && x<n && y>=0 && y<m; 34 } 35 36 void solve() 37 { 38 int minn=INF; 39 for(int state=0;state<(1<<m);state++) 40 { 41 memset(cnt,0,sizeof(cnt)); 42 memcpy(t,a,sizeof(int)*MAX_N*MAX_N); 43 int tot=0; 44 for(int j=0;j<m;j++) 45 { 46 int pos=m-j-1; 47 if((state>>pos)&1) 48 { 49 t[0][j]^=1; 50 cnt[0][j]=1; 51 tot++; 52 for(int k=0;k<4;k++) 53 { 54 int x=dx[k]; 55 int y=j+dy[k]; 56 if(is_legal(x,y)) t[x][y]^=1; 57 } 58 } 59 } 60 for(int i=1;i<n;i++) 61 { 62 for(int j=0;j<m;j++) 63 { 64 if(t[i-1][j]) 65 { 66 t[i][j]^=1; 67 cnt[i][j]=1; 68 tot++; 69 for(int k=0;k<4;k++) 70 { 71 int x=i+dx[k]; 72 int y=j+dy[k]; 73 if(is_legal(x,y)) t[x][y]^=1; 74 } 75 } 76 } 77 } 78 bool is_white=true; 79 for(int j=0;j<m;j++) 80 { 81 if(t[n-1][j]) 82 { 83 is_white=false; 84 break; 85 } 86 } 87 if(is_white && tot<minn) 88 { 89 memcpy(ans,cnt,sizeof(int)*MAX_N*MAX_N); 90 minn=tot; 91 } 92 } 93 if(minn==INF) failed=true; 94 } 95 96 void print() 97 { 98 if(failed) 99 { 100 cout<<"IMPOSSIBLE"<<endl; 101 return; 102 } 103 for(int i=0;i<n;i++) 104 { 105 for(int j=0;j<m;j++) 106 { 107 cout<<ans[i][j]; 108 if(j!=m-1) cout<<" "; 109 } 110 cout<<endl; 111 } 112 } 113 114 int main() 115 { 116 read(); 117 solve(); 118 print(); 119 }