1. 程式人生 > >Fliptile【構造+貪心列舉】

Fliptile【構造+貪心列舉】

題目連結


  我們列舉第一列的答案,然後我們以此為基礎向下搜尋,題目要我們找的是‘1’數最少並且在‘1’數相等的時候,字典序最小的答案,直接按順序列舉即可。

  給幾組測試樣例,過了這幾組,就是基本過了,一道構造題,卡了為好幾個小時……


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define son1 (j-1)>0? ans[i-1][j-1] : 0
#define son2 (j+1)<=M? ans[i-1][j+1] : 0
#define son3 (i-2)>0? ans[i-2][j] : 0
#define copppy(pr, ans) memcpy(pr, ans, sizeof(ans))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 18;
int N, M, mp[maxN][maxN], ans[maxN][maxN], cnt, pr[maxN][maxN], now;
bool check()
{
    now = 0;
    for(int i=1; i<=M; i++) if(ans[1][i]) now++;
    for(int i=2; i<=N; i++)
    {
        for(int j=1; j<=M; j++)
        {
            int s1 = son1, s2 = son2, s3 = son3;
            int tmp = mp[i-1][j] + s1 + ans[i-1][j] + s2 + s3;
            if( tmp & 1 ) { ans[i][j] = 1; now++; }
            else ans[i][j] = 0;
        }
    }
    for(int i=1; i<=M; i++) if( (ans[N-1][i] + mp[N][i] + ans[N][i-1] + ans[N][i+1] + ans[N][i]) & 1) return false;
    return true;
}
bool dfs_first_line(int y, int val)
{
    ans[1][y] = val;
    if(y == M)
    {
        bool flag = check();
        if(flag && cnt>now)
        {
            cnt = now;
            copppy(pr, ans);
        }
        return flag;
    }
    bool flag = dfs_first_line(y+1, 0);
    if(!flag) flag = dfs_first_line(y+1, 1);
    else dfs_first_line(y+1, 1);
    return flag;
}
int main()
{
    while(scanf("%d%d", &N, &M)!=EOF)
    {
        memset(ans, 0, sizeof(ans));
        memset(pr, 0, sizeof(pr));
        for(int i=1; i<=N; i++) for(int j=1; j<=M; j++) scanf("%d", &mp[i][j]);
        bool flag = false;
        cnt = INF;
        flag = dfs_first_line(1, 0);
        if(!flag) flag = dfs_first_line(1, 1);
        else dfs_first_line(1, 1);
        if(flag)
        {
            for(int i=1; i<=N; i++)
            {
                for(int j=1; j<=M; j++)
                {
                    printf("%d%c", pr[i][j], j==M?'\n':' ');
                }
            }
        }
        else printf("IMPOSSIBLE\n");
    }
    return 0;
}
/*
2 3
1 1 0
1 0 0
 ans:
1 0 0
0 0 0
/////
2 2
1 1
1 1
 ans:
1 1
1 1
/////
5 3
1 1 0
1 0 1
1 0 0
0 1 1
1 1 1
 ans:
0 0 0
1 1 0
1 0 0
1 0 0
0 0 1
 mine:
1 0 0
0 0 0
0 0 1
1 1 1
0 0 0
*/