kuangbin专题一 简单搜索 翻转(POJ-3279)

Posted MAKISE004

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kuangbin专题一 简单搜索 翻转(POJ-3279)相关的知识,希望对你有一定的参考价值。

Fliptile

Time Limit: 2000MS Memory Limit: 65536K

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


题目大意

给一个 n * m 矩阵,矩阵中只有0和1两种值,现在我们需要将矩阵中所有的元素变为0。我们可以进行一种翻转的操作,若选定(i,j)翻转,同时须将其上、下、左、右四个方向进行翻转(翻转即0变成1,1变成0)。问步数最少且字典序最小的方案。输出一个矩阵,1代表(i,j)被翻转,0代表不被翻转。



解题思路

这道题很容易让人联想到一道题 ———— 费解的开关,其实几乎完全一样的递推做法,只不过需要输出具体的方案,只需要另开一个数组存储具体方案即可。题目中要求字典序最小,因为是从上往下递推的,所以只需要记录步数最短的第一个方案就可以了。

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, pii> psi;
typedef __int128 int128;
#define x first
#define y second
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;

#include<iostream>
#include<cstring>
using namespace std;

const int N = 16;
int g[N][N], backup[N][N];   //当前图状态  图状态备份
int ans[N][N], tmp[N][N];    //记录答案  当前翻转方案
int n, m;
int minstep = 1e9;
int dx[4] = 1, -1, 0, 0;
int dy[4] = 0, 0, 1, -1;

//翻转
void turn(int x, int y)
    g[x][y] ^= 1;
    for(int k = 0; k < 4; k ++ )
        int nx = x + dx[k], ny = y + dy[k];
        if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
        g[nx][ny] ^= 1;
    


int main()
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin >> n >> m;
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < m; j ++ ) 
            cin >> g[i][j];

    //状态压缩  枚举状态  二进制为1表示第一行次列进行翻转
    for(int sta = 0; sta < (1 << m); sta ++ )
        memset(tmp, 0, sizeof(tmp));
        memcpy(backup, g, sizeof(g));

        int step = 0;    //得到第一行的状态
        for(int k = 0; k < m; k ++ )
            if(sta >> k & 1)
                tmp[0][k] = 1;
                turn(0, k);
                step ++ ;
            
        

        for(int i = 0; i < n - 1; i ++ )   //查看0-n-2行的状态,第(i + 1, j)处若为1需翻转其下面的位置
            for(int j = 0; j < m; j ++ )
                if(g[i][j] == 1)
                    tmp[i + 1][j] = 1;
                    turn(i + 1, j);
                    step ++ ;
                
            
        

        bool all_dark = true;          //查看最后一行是否全为0
        for(int i = 0; i < m; i ++ )
            if(g[n - 1][i])
                all_dark = false;
                break;
            

        if(all_dark && step < minstep) //更新答案
            memcpy(ans, tmp, sizeof(tmp));
            minstep = step;
        

        memcpy(g, backup, sizeof(backup));
    

    if(minstep == 1e9)
        cout << "IMPOSSIBLE" << endl;
        return 0;
    
    
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < m; j ++ )
            cout << ans[i][j] << \' \';
        cout << endl;
    

    return 0;

‘简单’搜索专题总结

  kuangbin专题一

A. 棋盘问题

  在是棋盘的格子上放置棋子,其中要求所有棋子不同行也不同列,求摆放的方案数。

  dfs,参数:行、棋子数,遍历的时候要回溯。

B. Dungeon Master

  走迷宫,3D的走迷宫。

C. Catch That Cow

  最短时间找到那只牛。 bfs,剪枝。

D. FilpTile

  翻方块,上一行状态决定下一行的翻转。

E. Find The Multiple

  大胆的bfs,数据范围很小的。

F. Prime Path

  bfs

G. Shuffle‘m Up

  直接模拟

H. Pots

  弄清楚水的状态是什么。

I. Fire Game

  枚举两两点grass点,放入队列,bfs取最小

J. Fired

  火先“行”,joe紧跟,bfs

K. 迷宫问题

  bfs,路径记录

L. Oil Deposits

  dfs连通块

M. 非常可乐

  和Pots异曲同工

N. Find A Way

  枚举KFC位置来bfs果断TLE,,,实际上,两人分别bfs,记录距离,求到KFC的距离的最小。

以上是关于kuangbin专题一 简单搜索 翻转(POJ-3279)的主要内容,如果未能解决你的问题,请参考以下文章

‘简单’搜索专题总结

kuangbin专题一 简单搜索 石油储备(HDU-1241)

kuangbin专题总结一 简单搜索

Dungeon Master POJ - 2251 [kuangbin带你飞]专题一 简单搜索

[kuangbin带你飞]专题一 简单搜索 bfs B - Dungeon Master

[kuangbin带你飞]专题一 简单搜索 Find a way HDU - 2612