POJ 3279 Fliptile

发布于 2020-04-09  1942 次阅读


题意

给你一个01矩阵,矩阵大小为M x N。(1 <= M , N <= 15)

每次操作选择一个格子,使得该格子与上下左右四个格子的值翻转。 至少多少次操作可以使得矩阵中所有的值变为0?

请输出翻转方案,若没有方案,输出"IMPOSSIBLE”。

若有多种方案符合题意,请首先输出翻转次数最少的方案;若方案个数仍不唯一,则输出字典序最小的方案。

题解

枚举第一行的所有情况

从第二行开始到最后一行,如果当前格子的上一个行对应的格子为1,表示就要反转当前的格子

最后检验最后一行是否全为0

代码

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
int mp[30][30], tmp[30][30];
int n, m;
int dx[5] = {0, 0, 0, 0, -1};
int dy[5] = {0, 0, -1, 1, 0};//四个方向分别是自己,上,左,右
int pr[30][30];//答案数组
int work()
{
    for (int i = 1; i < n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            int t = mp[i][j], cnt = 0;//t表示当前块是1还是0
            for (int k = 1; k <= 4; k++)//前一行的四个方向
            {
                int x = i + dx[k];
                int y = j + dy[k];
                t += tmp[x][y];//如果本身是1,奇数次反转还是0,偶数次反转是1,本身是0反之
            }
            if (t & 1)//如果当前块是1
                tmp[i+1][j] = 1;//下一行对应的块换为1保证当前为0
        }
    }
    //检验最后一行是否为0
    int i = n;
    for (int j = 1; j <= m; j++)
    {
        int t = mp[i][j], cnt = 0;
        for (int k = 1; k <= 4; k++)
        {
            int x = i + dx[k];
            int y = j + dy[k];
            t += tmp[x][y];
        }
        if (t & 1)//不合格就推出
            return -1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (tmp[i][j] & 1)
                ans++;
    return ans;
}
int main()
{
    // freopen("a.in","r",stdin);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> mp[i][j];
    int ans = 0x3f3f3f3f;
    for (int i = 0; i < (1 << n); i++)
    {
        memset(tmp,0,sizeof(tmp));
        for (int j = 0; j < m; j++)
            tmp[1][j+1] = (i >> j) & 1;//枚举第一行的所有情况
        int t = work();
        if (t == -1)
            continue;
        if (ans > t){
            ans =t;
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= m; j++)
                    pr[i][j] = tmp[i][j];
        }
    }
    if(ans==0x3f3f3f3f)
        return cout<<"IMPOSSIBLE"<<endl,0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
            cout << pr[i][j] << ' ';
        cout << endl;
    }
    return 0;
}

Humble Halten