Poj 3279Fliptile(二进制枚举)

题目传送门

题意:给定0,1矩阵,每次反转一个位置,它相邻的四个位置也会反转(如果存在的话),反转的意思就是1->0或者1->0,问最少反转多少个位置就可以使矩阵全部变成0。最后输出一个矩阵,所有反转的位置输出1,否则输出0,若存在多个答案相同,则输出矩阵字典序最小的一个。

先从第一行开始反转,利用二进制进行枚举,枚举第一行所有的可能选择,当第一行反转的确定了之后,后面每一行都随之确定了,第二行开始逐个元素进行判断,若该元素同一列的上一个元素为1,那么反转当前元素,最后全部枚举之后,只有最后一行可能有1,判断一下即可。

二进制枚举的过程就保证了字典序小的在前。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <sstream>
#include <cstring>
#include <set>
#include <cctype>
#include <bitset>
#define IO                       \
    ios::sync_with_stdio(false); \
    // cin.tie(0);                  \
    // cout.tie(0);
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int maxm = 1e6 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const LL mod = 11092019;
int dis[8][2] = {0, 1, 1, 0, 0, -1, -1, 0, 1, -1, 1, 1, -1, 1, -1, -1};
int a[20][20];
int b[20][20];
int temp[20][20];
int ans[20][20];
int res = inf;
int n, m;
void filp(int x, int y)
{
    for (int i = 0; i < 4; i++)
    {
        int tx = x + dis[i][0];
        int ty = y + dis[i][1];
        b[tx][ty] = !b[tx][ty];
    }
}
int rep()
{
    int cnt = 0;
    for (int j = 0; j < m; j++)
        if (temp[0][j])
        {
            cnt++;
            b[0][j] = !b[0][j];
            filp(0, j);
        }
    for (int i = 1; i < n; i++)
        for (int j = 0; j < m; j++)
            if (b[i - 1][j])
            {
                cnt++;
                b[i][j] = !b[i][j];
                temp[i][j] = 1;
                filp(i, j);
            }
    for (int j = 0; j < m; j++)
        if (b[n - 1][j] == 1)
            return inf;
    return cnt;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#endif
    // IO;
    cin >> n >> m; // n 行 m 列
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];
    for (int s = 0; s < (1 << m); s++)
    {
        memset(temp, 0, sizeof temp);
        memcpy(b, a, sizeof a);
        for (int j = 0; j < m; j++)
            if (s & (1 << j))
                temp[0][j] = 1;
        int t = rep();
        if (t < res)
        {
            res = t;
            memcpy(ans, temp, sizeof temp);
        }
    }
    if (res == inf)
        cout << "IMPOSSIBLE";
    else
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m - 1; j++)
                printf("%d ", ans[i][j]);
            printf("%d\n", ans[i][m - 1]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44115065/article/details/106148510
今日推荐