poj 3279 Fliptile

来源:互联网 发布:淘宝店铺宝贝不见了 编辑:程序博客网 时间:2024/05/15 00:41

思路很简单,只是写不出来代码。先确定第一行的翻转方法,然后翻转第二行到最后一行。确定第一行后,就可以通过翻转第二行来让第一行的黑色瓷砖翻转成白色的,然后再翻转第三行的瓷砖让第二行变成全白色的,一直到最后一行,然后再判断最后一行是否全是白色瓷砖。
本来看的《挑战程序设计竞赛》上的题解,可是没有看懂那个查询瓷砖颜色的函数,然后又看了个别的题解,链接:http://blog.csdn.net/wr132/article/details/45250529。。注释很详细。

#include <iostream>#include <cstring>using namespace std;const int MAXN = 17;int G[MAXN][MAXN],tile[MAXN][MAXN],flip[MAXN][MAXN];int cnt,n,m;int x[4] = {0,0,-1,1};int y[4] = {-1,1,0,0};void rev(int i, int j){    ++cnt;    flip[i][j] = 1;    tile[i][j] = !tile[i][j];    for(int k = 0; k < 4; ++k)        if(i+x[k] > -1 && j+y[k] > -1)            tile[i+x[k]][j+y[k]] ^= 1;}bool calc(int k){    cnt = 0;    memcpy(tile,G,sizeof(G));    for(int j = 0; j < m; ++j)        if(k & (1 << (m-1-j)))           rev(0,j);    for(int i = 1; i < n; ++i)        for(int j = 0; j < m; ++j)            if(tile[i-1][j]) rev(i,j);    for(int j = 0; j < m; ++j)        if(tile[n-1][j]) return false;    return true;}int main(){    int ans,p;    while(cin >> n >> m)    {        for(int i = 0; i < n; ++i)            for(int j = 0; j < m; ++j)                cin >> G[i][j];        ans = n*m+1,p=-1;        for(int i = 0; i < (1<<m); ++i)            if(calc(i) && cnt < ans)                ans = cnt, p = i;        memset(flip,0,sizeof(flip));        if(p >= 0)        {            calc(p);            for(int i = 0; i < n; ++i)            {                for(int j = 0; j < m; ++j)                    cout << flip[i][j] << " ";                cout << endl;            }        }        else            cout << "IMPOSSIBLE" << endl;    }    return 0;}
0 0