D - 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

题目大意:

给一个01矩阵,问能不能通过有限次的翻转使得矩阵内的元素全部变成零,每一次翻转,周围上下左右的方块都需要转。如果能,输出最小的翻转次数对应的翻转的方块的矩阵,如果不能输出“IMPOSSIBLE”。

具体思路:

用到遍历,就是对第一行进行遍历,然后逐行进行。判断是不是翻转的条件的就是这个方块的上一个是不是需要翻转。注意第一行需要枚举每一种情况,这个地方需要用到二进制枚举,如果一共有n列,一共有二的n次方多种情况。

#include
using namespace std;
# define INF 0x3f3f3f3f
int mapp[20][20];//用来存原图
int out[20][20];//用来存需要输出的图
int cal[20][20];//过渡矩阵
int n,m;
int f[5][2]= {{0,0},{1,0},{-1,0},{0,1},{0,-1}};//判断一个点需不需要翻转的条件,需要从五个点来判断,起始点,四个方向。
int judge(int s1,int s2)
{
    int temp=mapp[s1][s2];
    for(int i=0; i<5; i++)
    {
        int xi=s1+f[i][0];
        int yi=s2+f[i][1];//这个地方一定要注意哪一个才是中心
        if(xi<1||xi>n||yi<1||yi>m)continue;
        temp+=cal[xi][yi];
    }
    return temp%2;
}

int dfs()
{
    for(int i=2; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            if(judge(i-1,j))
                cal[i][j]=1;
        }
    for(int j=1; j<=m; j++)
    {
        if(judge(n,j))
            return -1;
    }//对最后一行进行判断,如果最后一行有需要翻转的,直接不符合条件,因为若翻转的话,上一个也需要翻转,这个违反题目条件了
    int num=0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            if(cal[i][j]==1)
                num++;
        }
    return num;
}
int main()
{
    while(cin>>n>>m)
    {
        int flag=0;
        int cnt=INF;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
                cin>>mapp[i][j];
        }
        for(int i=0; i<(1<         {
            memset(cal,0,sizeof(cal));
            for(int j=1; j<=m; j++)
                cal[1][m-j+1]=(i>>(j-1)) & 1;
            int temp=dfs();
            if(temp>=0&&temp             {
                flag=1;
                cnt=temp;
                memcpy(out,cal,sizeof(cal));//赋值给过渡矩阵
            }
        }
        if(flag==0)
            cout<<"IMPOSSIBLE"<         else
        {
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    if(j!=1)
                        cout<<" ";
                    cout<                 }
                cout<             }
        }

    }
    return 0;
}

 

 

 

你可能感兴趣的:(dfs,/,bfs)