【题目描述】
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”.
农夫John知道,一头智力满意的牛是一头快乐的母牛,它会提供更多的牛奶。他为牛安排了一项聪明的活动,他们在其中操纵方形瓷砖的M×N(1≤M≤15;1≤N≤15)的网格,一边是黑色的,另一边是白色的。
正如人们所猜测的那样,当一个白色的瓷砖被翻转时,它会变成黑色的;当一个黑色的瓷砖被翻转时,它就会变成白色的。牛群在翻转瓷砖时会得到奖励,当每个瓷砖都白色的一面朝上。然而,母牛有相当大的蹄子,当他们试图翻转一个瓷砖,他们也翻转所有相邻的瓷砖(与翻转的瓷砖有一个完整的边缘)。由于翻转是累人的,奶牛希望尽量减少它们必须做的翻转的数量。
帮助奶牛确定所需的最小翻转次数,以及达到最小值时翻转的位置。如果有多种方法可以最小的翻转量完成任务,则返回输出当将其视为字符串时字典顺序最小的方法。如果不可能完成这个任务,就打印”IMPOSSIBLE“。
【输入】
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
第1行:两个用空格隔开的整数,M和N
第2行到第M+1行:第i+1行N个用空格隔开的整数表示第i行的N块瓷砖,1表示黑,0表示白
【输出】
Lines 1… M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.
第1行到第M行:每一行包含N个用空格隔开的整数,每个表示在当前位置翻转的次数
【样例输入】
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
【样例输出】
0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0
题目链接:https://cn.vjudge.net/problem/POJ-3279
大致思路:翻转的前后顺序不影响最后结果,在任何一个位置的翻转不需要超过1次,局部枚举第1行的情况,在第1行确定时,后续m-1行都是确定的,只需检查最后一行是否符合要求即可。
代码如下:
#include <iostream>
#include <cstring>
using namespace std;
static const int MAXN=15;
int dx[]={0,0,0,1,-1},dy[]={1,-1,0,0,0};
bool mp[MAXN+2][MAXN+2],mp1[MAXN+2][MAXN+2],op[1<<MAXN][MAXN+2][MAXN+2];//mp1用来保存初始数据,在每一轮操作前还原mp,op用来记录所有的操作
int m,n,minstep=0x7fffffff,minkey;
void dfs(int x,int press,int key)
{
if(x<n)
{
op[key][1][x+1]=0;
dfs(x+1,0,key);//在第1行第x列不翻转
for(int i=1;i<=x;i++)
op[key+(1<<x)][1][i]=op[key][1][i];//key改变后需要复制前面的操作
op[key+(1<<x)][1][x+1]=1;
dfs(x+1,1,key+(1<<x));//在第1行第x列翻转
}
if(x==n)
{
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
mp[i][j]=mp1[i][j];//每一轮操作前还原mp
int step=0;
for(int i=1;i<=n;i++)
if(op[key][1][i])
{
step++;
if(step>=minstep) return;
for(int j=0;j<5;j++)
mp[1+dx[j]][i+dy[j]]=!mp[1+dx[j]][i+dy[j]];
}//对当前情况的第1行进行操作
for(int i=2;i<=m;i++)
for(int j=1;j<=n;j++)
if(mp[i-1][j])
{
step++;
if(step>=minstep) return;
op[key][i][j]=1;
for(int k=0;k<5;k++)
mp[i+dx[k]][j+dy[k]]=!mp[i+dx[k]][j+dy[k]];
}//在第1行确定的情况下,后续m-1行的操作都是确定的
for(int i=1;i<=n;i++)
if(mp[m][i]) return;//检查最后一行是否符合要求即可
if(step<minstep)
{
minstep=step;
minkey=key;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0),cout.tie(0);
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
cin>>mp[i][j];
mp1[i][j]=mp[i][j];
}
op[0][1][1]=0;
dfs(1,0,0);//在第1行第1列不翻转
op[1][1][1]=1;
dfs(1,1,1);//在第1行第1列翻转
if(minstep==0x7fffffff)
cout<<"IMPOSSIBLE"<<endl;
else
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
{
cout<<op[minkey][i][j];
if(j==n)
cout<<endl;
else
cout<<" ";
}
return 0;
}

306

被折叠的 条评论
为什么被折叠?



