POJ3279 二进制的搜索

Fliptile

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

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

Output

Lines 1.. M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.

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

题目大意:有一个M*N的10组成的矩阵,其中0代表白色的砖块,1代表黑色的砖块,要求将所有的黑色瓷砖转化为白色瓷砖,转化方式是踩上黑色的瓷砖上就能翻转为白色,同理白色也能翻转为黑色,反转的同时会将其上下左右的所有的砖块都翻转,每翻转一次就要将翻转的次数标记到相应的点上工行,然后输出这些值,如果有多组答案按字典序输出。

如何按字典序输出?那就要保证第一行的翻转位置都要从最后面开始,还有一个地方要知道的是每一行的情况是有2^n个情况,因此,我们可以枚举二进制的01的位置来模拟翻转的位置,这样不仅能将所有的情况输出出来,而且还能保证翻转的情况都是从小的情况开始的,举个栗子:如果第一行的001100与000101都是能够得到答案的,但是000101出现的比001100早,字典序小,因此我们选择000101这种翻转情况。

在这里只对第一行的所有的情况进行处理,从上面的那一段可以知道处理的方式有2^n中,只要第一行的 情况确定了,那么下面的m-1行的操作都是确定的,比如第一行决定翻转的是哪几块的时候,那么,第二行就要将第一行的1转化为0,这样第一行就全部为0,同理第三行也要进行,最终只要看最后一行的是否也是全为0,如果是的话,那就可以说明是当前第一行的操作是满足题意的。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ms(a,b) memset(a,b,sizeof a)
const int  MAX=0x3f3f3f3f;
const int N=1e6+10;
typedef long long ll;
int ans[20][20];
int map[20][20];
int n,m;
int f[20][20];
int a[20][20];
int turnaum,turnans;
void Turn(int x,int y)
{
    turnaum++;
    f[x][y]=1;
    a[x][y]=!a[x][y];
    a[x-1][y]=!a[x-1][y];a[x+1][y]=!a[x+1][y];
    a[x][y-1]=!a[x][y-1];a[x][y+1]=!a[x][y+1];
}
int main()
{
    scanf("%d%d",&m,&n);
    rep(i,1,m)
    rep(j,1,n)
    scanf("%d",&map[i][j]);
    int t=1<<n;//第一行所有的翻转组合数,通过二进制来存储
    int turnans=N;
    rep(p,0,t)
    {
    turnaum=0;
    ms(f,0);
        memcpy(a,map,sizeof map);
        int loop=p;
        rep(i,1,n)//枚举第一行需要翻转的情况
        {
            if(loop&1) 
    Turn(1,i);
                loop>>=1;
        }
        rep(i,2,m)//枚举剩下的m-1行
        rep(j,1,n)
        if(a[i-1][j])//通过翻转第i行,将i-1为1的情况翻转为0,这样就尽量使每一行都是通过下一行转变为0的
            Turn(i,j);
        int l;
        for(l=1;l<=n;l++)
        if(a[m][l])
            break;//经过上面的的一次次枚举,肯定能够保证前m-1行都是0,那只要最后一行都是0就能使全部的情况都变成0
        if(l==n+1&&turnaum<turnans)
        {
            turnans=turnaum;
            memcpy(ans,f,sizeof f);
        }
    }
    if(turnans==N){
        printf("IMPOSSIBLE\n");
        return 0;
    }
    rep(i,1,m)
    {
        rep(j,1,n)
        printf("%d ",ans[i][j]);
        printf("\n");
    }
}

 

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值