POJ3279 Fliptile 【DFS】

Fliptile

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 3487   Accepted: 1351

Description

Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles,
each of which is colored black on one side and white on the other side.

As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather
large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.

Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the
output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".

Input

Line 1: Two space-separated integers: M and N

Lines 2..M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white

Output

Lines 1..M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.

Sample Input

4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1

Sample Output

0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0

Source

USACO 2007 Open Silver

/*
** Problem: POJ3279
** Status: Accepted
** Running time: 407ms
** Complier: C++
** Author: Changmu
**
** 题意:有一个M*N的棋盘,每一个格子只有两种状态0或1,每次可以选择一个
** 格子执行翻转操作,并且与该格子相邻的4个格子都会被翻转,求将所有格子
** 都翻转成0所需要的最小操作数,若有多种方案,输出字典序最小的方案数。
**
** 题解:枚举第一行的所有翻转状态,在此基础上深搜剩余行的翻转状态。
*/

#include <stdio.h>
#include <string.h>

#define maxn 16
#define inf 0x3f3f3f3f

int cow[maxn][maxn], M, N; // 原始数据 M rows
int flip[maxn][maxn]; // 保存中间结果
int opt[maxn][maxn]; // 保存最优结果
const int mov[][2] = {0, 0, 0, -1, 0, 1, -1, 0}; // 中左右上

void getMap() {
    int i, j;
    for(i = 0; i < M; ++i)
        for(j = 0; j < N; ++j)
            scanf("%d", &cow[i][j]);
}

int getColo(int x, int y) {
    int c = cow[x][y], xa, ya, i;
    for(i = 0; i < 4; ++i) {
        xa = x + mov[i][0];
        ya = y + mov[i][1];
        if(xa >= 0 && xa < M && ya >= 0 && ya < N) {
            c += flip[xa][ya];
        }
    }
    return c & 1;
}

int DFS(int k) {
    int i, j, sum;
    if(k == M - 1) { // 最后一行不再翻转,判断是否都0
        for(i = 0; i < N; ++i)
            if(getColo(k, i)) break;
        if(i != N) return -1;
        // 统计翻转次数
        for(i = sum = 0; i < M; ++i)
            for(j = 0; j < N; ++j)
                if(flip[i][j]) ++sum;
        return sum;
    }
    for(j = 0; j < N; ++j)
        if(getColo(k, j)) flip[k + 1][j] = 1;
    return DFS(k + 1);
}

void solve() {
    int i, j, maxCase = 1 << N, ret = inf, num, tmp;
    for(i = 0; i < maxCase; ++i) {
        memset(flip, 0, sizeof(flip));
        for(j = N - 1, tmp = i; j >= 0; --j, tmp >>= 1) {
            flip[0][j] = tmp & 1;
        }
        num = DFS(0);
        if(num != -1 && num < ret) {
            ret = num;
            memcpy(opt, flip, sizeof(flip));
        }
    }

    if(ret == inf) printf("IMPOSSIBLE\n");
    else {
        for(i = 0; i < M; ++i)
            for(j = 0; j < N; ++j)
                if(j == N - 1) printf("%d\n", opt[i][j]);
                else printf("%d ", opt[i][j]);
    }
}

int main() {
    // freopen("stdin.txt", "r", stdin);
    while(scanf("%d%d", &M, &N) == 2) {
        getMap();
        solve();
    }
    return 0;
}
时间: 2024-07-30 13:50:42

POJ3279 Fliptile 【DFS】的相关文章

poj 3009 Curling 2.0 【DFS】

题意:从2出发,要到达3, 0可以通过,碰到1要停止,并且1处要变成0, 并且从起点开始沿着一个方向要一直前进,直至碰到1(或者3)处才能停止,(就是反射来反射去知道反射经过3).如果反射10次还不能到达3,就输出-1. 策略:深搜. 易错点,方向不容易掌握,并且,出题人把n, m顺序反了. 代码: #include<stdio.h> #include<string.h> int map[25][25]; int ans, n, m; const int dir[4][2] = {

NYOJ 587 blockhouses 【DFS】

blockhouses 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall. A blockhouse is a small castle th

NYOJ 722 数独 【DFS】+【预处理】

数独 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 数独是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个3*3宫内的数字均含1-9,不重复. 每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的. 有一天hrdv碰到了一道号称是世界上最难的数独的题目,作为一名合格的程序员,哪能随随便便向困难低头,于是他决定编个程序来解决它.. 输入 第一行有一个

poj 1011 Sticks 【DFS】+【剪枝】

题意:有未知根(长度一样)木棒(小于等于n),被猪脚任意的截成n段,猪脚(脑抽了)想知道被截之前的最短长度(我推测猪脚得了健忘症). 这道题光理解题意就花了好久,大意就是任意根被截后的木棒拼到一起,能不能组成s(<=n)根的相同的木棒, 例:数据 9  5 1 2 5 1 2 5 1 2 可以组成最短为6 的(5+1, 2+2+2)3根木棒. 策略:深搜. 不过要是传统的深搜的话,TLE妥妥的.所以要剪枝(所谓剪枝,就是多加几个限制条件). 话不多说直接上代码. 代码1: #include <

HDU1010 Tempter of the Bone 【DFS】+【剪枝】

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 70895    Accepted Submission(s): 19535 Problem Description The doggie found a bone in an ancient maze, which fascinated him a

nyoj 325 zb的生日 【DP】||【DFS】

两种方法: 第一种:将总数一半当做背包,用总数-2*最多能装的数目就是所求: 第二种:深搜: zb的生日 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能

【dfs】hdu 1016 Prime Ring Problem

[dfs]hdu 1016 Prime Ring Problem 题目链接 刚开始接触搜索,先来一道基本题目练练手. 注意对树的深度进行dfs dfs过程中注意回退!!! 素数提前打表判断快一些 参考代码 /*Author:Hacker_vision*/ #include<bits/stdc++.h> #define clr(k,v) memset(k,v,sizeof(k)) using namespace std; const int _max=1e3+10;//素数打表 int n,pr

hdoj 1045 Fire Net 【DFS】

题意:如果两个点要放在同一行或者同一列,那么两个点中间要有一个墙,否则的话只能放一个点,最后问你最多能放几个点. 看了一个星期.. 这道题的解法我还是第一次见,就是逐个逐个的来放置每个点,然后每经过一个点都判断一次,详情看代码 代码: #include <stdio.h> #include <string.h> int ans, n; char map[10][10]; int judge(int lin, int row) { int i; for(i = lin-1; i &g

【DFS】【拓扑排序】【动态规划】Gym - 100642A - Babs&#39; Box Boutique

给你10个箱子,有长宽高,每个箱子你可以决定哪个面朝上摆.把它们摞在一起,边必须平行,上面的不能突出来,问你最多摆几个箱子. 3^10枚举箱子用哪个面.然后按长为第一关键字,宽为第二关键字,从大到小排序. 如果前面的宽大于等于后面的宽,就连接一条边. 形成一张DAG,拓扑排序后跑最长路即可. #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespa