题目链接: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 }
时间: 2024-10-01 04:49:40