1. 程式人生 > >POJ 3279 Fliptile(翻轉)

POJ 3279 Fliptile(翻轉)

amp log i++ ostream 翻轉 ring oss ret main

題目鏈接:http://poj.org/problem?id=3279

題意:n*m棋盤區域,由0和1填充,0白,1,黑,(正反兩面顏色各異)通過翻轉操作使棋盤全部白色朝上,每次翻轉棋子,棋子周圍(上下左右)都要被翻轉,問是否可能翻轉

翻轉成功,如果翻轉成功,輸出最少的翻轉次數下每個棋子的翻轉次數。

題解:有m列,所以最多有2^m種可能性,枚舉第一行。然後從第i行(i從2開始)先開始考慮第i-1行,然後依次往下推,再判斷最後一行是不是都翻轉成白色。

 1 #include <string>
 2 #include <cstring>
 3 #include <iostream>
 4
#include <algorithm> 5 using namespace std; 6 7 int n,m; 8 const int N=20; 9 const int INF=0x3f3f3f3f; 10 int dx[5]={0,0,0,1,-1}; 11 int dy[5]={0,1,-1,0,0}; 12 int map[N][N],temp[N][N],res[N][N]; 13 14 int get(int x,int y){ 15 int sum=map[x][y]; 16 for(int i=0;i<5;i++){ 17
int fx=x+dx[i],fy=y+dy[i]; 18 if(fx>=1&&fx<=n&&fy>=1&&fy<=m) 19 sum+=temp[fx][fy]; 20 } 21 return sum%2; 22 } 23 24 int cal(){ 25 for(int i=2;i<=n;i++) 26 for(int j=1;j<=m;j++) 27 if(get(i-1,j)) temp[i][j]=1
; 28 29 for(int j=1;j<=m;j++){ 30 if(get(n,j)) return -1; 31 } 32 33 int sum=0; 34 for(int i=1;i<=n;i++) 35 for(int j=1;j<=m;j++) 36 sum+=temp[i][j]; 37 return sum; 38 } 39 40 int main(){ 41 cin>>n>>m; 42 43 for(int i=1;i<=n;i++) 44 for(int j=1;j<=m;j++) 45 cin>>map[i][j]; 46 47 int en=1<<m; 48 int ans=INF; 49 for(int i=0;i<en;i++){ 50 memset(temp,0,sizeof(temp)); 51 for(int j=0;j<m;j++){ 52 temp[1][m-j]=(i>>j) & 1; 53 } 54 int cnt=cal(); 55 if(cnt>=0&&cnt<ans){ 56 ans=cnt; 57 memcpy(res,temp,sizeof(temp)); 58 } 59 } 60 if(ans==INF) {cout<<"IMPOSSIBLE"<<endl;return 0;} 61 for(int i=1;i<=n;i++){ 62 for(int j=1;j<=m;j++){ 63 if(j==1) cout<<res[i][j]; 64 else cout<<" "<<res[i][j]; 65 } 66 cout<<endl; 67 } 68 return 0; 69 }

POJ 3279 Fliptile(翻轉)