poj 3279 Filptile (USACO 2007 Open Silver)

来源:互联网 发布:javascript submit 编辑:程序博客网 时间:2024/05/16 08:21

题意:

n*m块区域,每一块有正反两面,两面分别是白色和黑色。

翻转一块区域的同时, 与其相邻的四块区域也会同时被反转 

问最少需要翻转的次数 ,使所有的区域都变成白色 输出其翻转方案 

思路:

枚举第一行的翻转状态

如果已经知道了第一行的状态,那么后面几行的状态就随之确定了——(如果该区域的上面一个区域是黑色,那这个区域必然是要反转才能让他上面的区域变成白色)

然后比较和记录最少的翻转次数 输出即可

code:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 20;const int INF = 0x3f3f3f3f;int maze[maxn][maxn], tmaze[maxn][maxn];int ans[maxn][maxn], min_ans[maxn][maxn];int n,m;void deal(int x, int y){    tmaze[x][y] ^= 1;    tmaze[x+1][y] ^= 1;    tmaze[x-1][y] ^= 1;    tmaze[x][y+1] ^= 1;    tmaze[x][y-1] ^= 1;}void deal1(int s){    int cnt = m;    for(int i = 0; i < m; i++){        ans[1][cnt--] = (s>>i)&1;    }}bool deal2(){    for(int i = 1; i <= m; i++){        if(ans[1][i] == 1){            deal(1,i);        }    }    for(int i = 2; i <= n; i++){        for(int j = 1; j <= m; j++){            if(tmaze[i-1][j] == 1){                ans[i][j] = 1;                deal(i,j);            }        }    }    bool flag = true;    for(int i = 1; i <= m; i++){        if(tmaze[n][i] != 0){            flag = false;        }    }    return flag;}void init(){    for(int i = 1; i <= n; i++){        for(int j = 1; j <= m; j++){            scanf("%d",&maze[i][j]);        }    }}void solve(){    bool flag;    bool flag2 = false;    int min_ = INF;    memset(min_ans, 0, sizeof(min_ans));    for(int s = 0; s < (1<<m); s++){        memset(ans, 0, sizeof(ans));        memcpy(tmaze, maze, sizeof(maze));        deal1(s);//获取第一行状态 放到ans[1][i] 中        flag = deal2();//依据第一行进行翻转        if(flag){//成功 则输出            flag2 = true;            int tmp = 0;            for(int i = 1; i <= n; i++){                for(int j = 1; j <= m; j++){                    if(ans[i][j] == 1) tmp++;                }            }            if(tmp < min_){                memcpy(min_ans, ans, sizeof(ans));                min_ = tmp;            }        }    }    if(!flag2)        printf("IMPOSSIBLE\n");    else{        for(int i = 1; i <= n; i++){            for(int j = 1; j <= m; j++){                if(j != 1) printf(" ");                printf("%d",min_ans[i][j]);            }            printf("\n");        }    }}int main(){    scanf("%d%d",&n,&m);    init();    solve();    return 0;}



虽然这道题目起码做过3回了,但还是不记得怎么做的....简直无情T_T比赛的时候没有出...被虐成马



0 0