以防萬一,題目原文和鏈接均附在文末。那么先是題目分析:
【一句話題意】
給定長寬的黑白棋棋盤擺滿棋子,每次操作可以反轉一個位置和其上下左右共五個位置的棋子的顏色,求要使用最少翻轉次數將所有棋子反轉為黑色所需翻轉的是哪些棋子(這句話好長...)。
【題目分析】
盯着奇怪的題目看了半天發現和奶牛沒什么卵關系..奶牛智商高了產奶高是什么鬼說法...
這題剛開始被放到搜索的分類下了..然而這和搜索有什么關系..沒經驗所以想了各種和搜索沾邊的方法,結果沒想出解法,直到看了網上的題解,壓根不是搜索啊有木有。
然后這題網上給的分類是簡單題..簡單題..蒟蒻跪了..
好了開始說解法。首先根據題目,每次操作都會影響到周圍的“棋子”,而要使得每個1都被反轉為0,那么我們就應當每次都反轉1下方的棋子以改變1為0.
那么,當我們處理過1到n-1行的時候,前n-1行就都已經是0了,最后我們只需要檢查最后一行是不是全部為0就可以檢查這次的出操作是否正確了。如果正確且最小,那就存起來。最后輸出,萬事大吉。
當然,因為我們要改變第x行的1為0需要反轉的是x+1行的位置。而這個整個規則是我們驗證一組操作是否能達到目的所用的,那么我們需要在驗證前先確定操作(沒操作怎么驗證..)。
於是根據規則內容可知,只需要能確認第一行的翻轉情況,就能夠推出下面所有的翻轉情況並驗證是否正確。於是需要做的就是枚舉第一行的情況了。
【算法流程】
整個代碼分了四部分,處理輸入部分沒啥可說的,接下來就是doWork干活部分了..
需要干的活就是枚舉第一行的所有情況然后對於每次枚舉都計算驗證是否符合要求以及反轉所需的次數。其中,第一行的狀態數量可以使用左移運算優化(效率比pow高),於是總共枚舉的數量就有1<<col次。另外,因為這使得一行的狀態是由一個數字保存的,所以依然使用位運算取得是否翻轉的狀態。
將枚舉好的一次首行狀態存好后就可以交給calc計算和驗證了。驗證就是通過上述翻轉規則操作。其中get(x,y)為取得某個位置是否為1的狀態的方法(過程)。
最后檢查結果就好。下面是代碼。
哦對了,我似乎濫用了each宏定義...無視即可。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <cstring> 5 #include <queue> 6 #define each(i,n) (int i=1;i<=(n);++i) 7 #define INF 0x3f3f3f3f 8 9 using namespace std; 10 11 int row,col; 12 int arr[20][20]; 13 int flip[20][20],ans[20][20]; 14 int dir[5][2] = { 15 0,0, 0,1, 0,-1, -1,0, 1,0 16 }; 17 18 int get(int x,int y) { 19 int c = arr[x+1][y+1]; 20 for(int i = 0;i<5;i++) { 21 int dx = x + dir[i][0]; 22 int dy = y + dir[i][1]; 23 if(dx >=0 && dx<row && dy>=0 && dy<col) { 24 c+=flip[dx][dy]; 25 } 26 } 27 return c&1; // with flip state, if odd return 1 28 } 29 30 int calc() { 31 for each(i,row-1) { 32 for(int j = 0;j<col;j++) { 33 if(get(i-1,j)) ++flip[i][j]; 34 } 35 } 36 for(int i=0;i<col;i++) { // check last line 37 if(get(row-1,i)) return 0; 38 } 39 int cnt = 0; 40 for (int i=0;i<row;i++) { //統計翻轉的次數 41 for (int j=0;j<col;j++) { 42 cnt += flip[i][j]; 43 } 44 } 45 return cnt; 46 } 47 48 49 void doWork() { 50 int cnt = INF; 51 for(int i=0;i<(1<<col);i++) { //from 0000 to 1111 52 memset(flip,0,sizeof(flip)); 53 for(int j=0;j<col;j++) { 54 flip[0][col-j-1] = (i>>j)&1; //get pos state form binary number 55 } 56 int num = calc(); 57 if (num<cnt && num!=0) { 58 cnt = num; 59 memcpy(ans,flip,sizeof(flip)); 60 } 61 } 62 if (cnt==INF) printf("IMPOSSIBLE\n"); 63 else { 64 for (int i=0;i<row;i++) { 65 printf("%d",ans[i][0]); 66 for each(j,col-1) { 67 printf(" %d",ans[i][j]); 68 } 69 printf("\n"); 70 } 71 } 72 } 73 74 int main() { 75 76 while(~scanf("%d%d",&row,&col)) { 77 memset(arr,0,sizeof(arr)); 78 for each(i,row) { 79 for each(j,col) { 80 scanf("%d",&arr[i][j]); 81 } 82 } 83 84 doWork(); 85 } 86 87 }
題目鏈接:Fliptile(POJ 3279)
題目屬性:枚舉 簡單優化 (我真不知道算不算搜索...)
相關題目:poj3276
題目原文:
【desc】
Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.
As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.
Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".
【In】
Line 1: Two space-separated integers: M and N
Lines 2.. M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white
【Out】
Lines 1.. M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.
【SampIn】
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
【SampOut】
0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0