码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3279 Filptile (USACO 2007 Open Silver)

时间:2015-04-14 07:19:47      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:poj

题意:

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比赛的时候没有出...被虐成马



poj 3279 Filptile (USACO 2007 Open Silver)

标签:poj

原文地址:http://blog.csdn.net/u013382399/article/details/45036443

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!