Fliptile (POJ - 3279, thinking + binary enumeration)

Posted by greenie2600 on Sat, 09 Nov 2019 17:41:11 +0100

1. Title link:

POJ-3279

2. Main idea:

I'll give you a picture, only 0 and 1.

0 for white, 1 for black

Every time a brick is knocked, the brick and the bricks in four directions around it will change color

Ask if you can turn all the bricks white

If possible, output the minimum dictionary order of the operation in the case of minimum steps

Otherwise, output "invisible"

Analysis:

Binary enumeration operation on the first line

And then the state of the first line. If the operation of the second line, for example (1, 2), is 1, you must hit (2, 2)

Handle all lines in the same way

After that, if the last line is all 0, then this scheme is feasible

4. Code implementation:

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = (int)15;
const int inf = 0x3f3f3f3f;

bool mp[M + 5][M + 5];///Initial map
bool ans[M + 5][M + 5];///Final operation method
bool cur[M + 5][M + 5];///Maps processed
bool operation[M + 5][M + 5];///Current operation method

void press(int x, int y)
{
    cur[x][y] = !cur[x][y];
    cur[x + 1][y] = !cur[x + 1][y];
    cur[x - 1][y] = !cur[x - 1][y];
    cur[x][y + 1] = !cur[x][y + 1];
    cur[x][y - 1] = !cur[x][y - 1];
}

int solve(int m, int n)
{
    int step = 0;
    memcpy(cur, mp, sizeof(mp));
    for(int i  = 1; i <= n; ++i)
    {
        if(operation[1][i])
        {
            press(1, i);
            step++;
        }
    }
    for(int i = 2; i <= m; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            if(cur[i - 1][j])
            {
                operation[i][j] = 1;
                press(i, j);
                step++;
            }
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        if(cur[m][i])
            return inf;
    }
    return step;
}

int main()
{
    int m, n;
    scanf("%d %d", &m, &n);
    for(int i = 1;i <= m; ++i)
    {
        for(int j = 1; j <= n; ++j)
        {
            scanf("%d", &mp[i][j]);
        }
    }
    int min_step = inf;
    for(int i = 0; i < (1<<n); ++i)
    {
        memset(operation, 0, sizeof(operation));
        for(int j = 0; j < n; ++j)
        {
            operation[1][n - j] = i>>j&1;///Ensure dictionary order
        }
        int step = solve(m, n);
        if(step < min_step)
        {
            min_step = step;
            memcpy(ans, operation, sizeof(operation));
        }
    }
    if(min_step < inf)
    {
        for(int i = 1; i <= m; ++i)
        {
            for(int j = 1;j <= n; ++j)
            {
                printf("%d%c", ans[i][j], j == n ? '\n' : ' ');
            }
        }
    }
    else
        printf("IMPOSSIBLE\n");
    return 0;
}