poj 3279 Fliptile 枚举 模拟

来源:互联网 发布:js dh算法 编辑:程序博客网 时间:2024/06/05 15:58

题目

题目链接:http://poj.org/problem?id=3279

题目来源:《挑战》例题。

简要题意:踩一个点翻转周围五个点,求全翻成白色的方案中残砖次数最少而且字典序最小的。

题解

我们可以首先确定第一行的翻转情况,这个用二进制枚举。

然后之后每一行的翻转情况就已经可以确定了,然后模拟出来就可以了。

算是比较经典的题,好像看到过不少类似的题。

代码

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#include <queue>#include <string>#include <vector>#include <set>#include <map>#define fi first#define se secondusing namespace std;typedef long long LL;typedef pair<int,int> PII;// headconst int N = 20;const int INF = 1e9;int dx[5] = {0, 0, 0, 1, -1};int dy[5] = {0, 1, -1, 0, 0};bool a[N][N];bool b[N][N];bool c[N][N];bool res[N][N];void duang(int x, int y) {    c[x][y] = true;    for (int i = 0; i < 5; i++) {        int cx = x + dx[i];        int cy = y + dy[i];        b[cx][cy] = !b[cx][cy];    }}bool checkLine(int x, int m) {    for (int i = 1; i <= m; i++) {        if (b[x][i]) return false;    }    return true;}void init(int n, int m, int mask) {    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            b[i][j] = a[i][j];            c[i][j] = false;        }    }    for (int i = 0; i < m; i++) {        if ((1<<i) & mask) {            duang(1, i+1);        }    }}bool process(int n, int m) {  for (int i = 1; i < n; i++) {    for (int j = 1; j <= m; j++) {            if (b[i][j]) {                duang(i+1, j);            }    }  }  return checkLine(n, m);}void printAns(int n, int m) {    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            printf("%d%c", res[i][j], j==m ? '\n' : ' ');        }    }}int getCnt(int n, int m) {    int ans = 0;    for (int i = 1; i <= n; i++) {        for (int j = 1; j <= m; j++) {            if (c[i][j]) ans++;        }    }    return ans;}int main() {    int n, m;    while (scanf("%d%d", &n, &m) == 2) {        for (int i = 1; i <= n; i++) {            for (int j = 1; j <= m; j++) {                scanf("%d", a[i]+j);            }        }        int mx = 1 << m;        int ans = INF;        for (int mask = 0; mask < mx; mask++) {            init(n, m, mask);            if (!process(n, m)) continue;            int temp = getCnt(n, m);            if (temp < ans) {                memcpy(res, c, sizeof res);                ans = temp;            }        }        if (ans == INF) {            puts("IMPOSSIBLE");        } else {            printAns(n, m);        }        memset(res, 0, sizeof res);    }    return 0;}
0 0
原创粉丝点击