Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 9926 | Accepted: 3692 |
Description
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".
Input
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
Output
Sample Input
4 4 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1
Sample Output
0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0题意:黑白棋都翻转成白色。规则是当我翻转其中一个时,它周围的4个棋子跟着它一块翻转。目标是用最少的步数把他们都翻转成白色,1代表黑,0代表白色;
思路:可以利用第一层的 2^n 种状态来进行枚举。依次翻转到最后一行,如果最后一行均为白色,那么这种第一层状态可以达到效果。记录下来,最后取最少翻转次数的结果输出。具体实现细节和相关解释在代码注释中给出。
(学到了利用二进制进行枚举的方便之处)
具体看代码就能看懂。这道题一看我就觉得不会,看了博客分析了一会儿,才看懂啥意思。(估计自己过不了几天就会忘了,毕竟不是自己想出来的东西,虽然懂了代码,但是还是不知道为什么这样能求出答案0.0)
AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<string>
#define LL long long
#define eps 1e-8
using namespace std;
const int mod = 1e7+7;
const int inf = 0x3f3f3f3f;
const int maxx = 100100;
const int N = 20;
int ma[N][N],ans[N][N],a[N][N];
int n,m,xx,yy,anss,flag;
int dx[7]= {0,1,0,0,-1};
int dy[7]= {0,0,1,-1,0};
int fuc(int x,int y)//判断颜色
{
int tem=ma[x][y];
for(int i=0; i<5; i++)
{
xx=x+dx[i];
yy=y+dy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m)
tem+=a[xx][yy];
}
return tem&1;
}
int dfs()
{
for(int i=1; i<n; i++)
for(int j=0; j<m; j++)
if(fuc(i-1,j))//看上一个是否为黑色。
a[i][j]=1;//若为黑色则翻转。
for(int i=0; i<m; i++)
if(fuc(n-1,i))//看最后一行的的棋子是否有黑色的。
return -1;
int tmp=0;//若都为白色则统计翻转次数
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
tmp+=a[i][j];
return tmp;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
anss=inf,flag=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
scanf("%d",&ma[i][j]);
for(int i=0; i< 1<<m; i++)
{
memset(a,0,sizeof(a));
for(int j=0; j<m; j++)
a[0][m-j-1]=i>>j&1;//转化为二进制存到a【0】【】中,注意顺序
int num=dfs();
if(num>=0&&anss>num)
{
flag=1;
anss=num;
memcpy(ans,a,sizeof(a));//跟新答案
}
}
if(!flag)
printf("IMPOSSIBLE\n");
else
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(j)printf(" ");
printf("%d",ans[i][j]);
}printf("\n");
}
}
}
return 0;
}