0
点赞
收藏
分享

微信扫一扫

POJ 3279 Fliptile(bfs+二进制+思维)

软件共享软件 2022-06-17 阅读 41

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

题目大意:有一个 M * N 的格子,每个格子可以翻转正反面,它们有一面是黑色,另一面是白色。黑色翻转之后变成白色,白色翻转之后则变成黑色。
游戏要做的是把所有的格子翻转为白色。不过因为牛蹄很大,所以每次翻转一个格子,与它上下左右相邻接的格子也会被翻转。
求用最小的步数完成时,每个格子的翻转次数。最小步数的解有多个时,输出字典序最小的一组;解不存在的话,则输出IMPOSSIBLE
思路
因为是求字典序最小,所以i要从0开始,每一行有n列,所有有2的n次方种情况,i的每一种情况都要展成二进制,然后把这个二进制赋给第一行,然后抓住这一行,先看第二行。在考察第二行时,就只是让第一行全部变成0,然后依次向下,每一行改前一行。剩下最后一行时,检查如果最后一行全是0,则符合条件,如果最后一行有1,就不符合条件了。

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

int nextt[5][2]={{1,0},{0,1},{0,-1},{-1,0},{0,0}};
int tile[20][20];//存地图
int opt[20][20];//保存最优解
int flip[20][20];//保存中间结果
int m, n;//m行n列

//查询(x,y)的颜色
int get(int x, int y)
{
int ans=tile[x][y];
for (int k=0; k<5; k++){
int tx=x+nextt[k][0];
int ty=y+nextt[k][1];
if (tx>=0&&tx<m&&ty>=0&&ty<n)
ans+=flip[tx][ty];
}
return ans%2;//状态压缩,翻转两次等于不翻转
}

int calc()
{
for (int i=1; i<m; i++)
for (int j=0; j<n; j++)
if (get(i-1, j)!=0)//看上一行
flip[i][j]=1;

for (int j=0; j<n; j++)
if (get(m-1, j)!=0)
return -1;

int ans=0;
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
ans+=flip[i][j];
return ans;
}

void solve()
{
int ans=-1;
for (int i=0; i<1<<n; i++){//2的n次方
memset(flip, 0, sizeof(flip));//每一种情况初始化都是不翻转
for (int j=0; j<n; j++)
flip[0][n-j-1]=i>>j & 1;//把i转成2进制,顺序赋给第一行

int num=calc();
if (num>=0 && (ans<0 || num<ans)){
ans=num;
memcpy(opt, flip, sizeof(flip));
}
}
if (ans<0)
printf("IMPOSSIBLE\n");
else{
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
printf("%d", opt[i][j]);
if (j!=n-1) printf(" ");
}
printf("\n");
}
}
}
int main()
{
scanf("%d%d", &m, &n);
for (int i=0; i<m; i++)
for (int j=0; j<n; j++)
scanf("%d", &tile[i][j]);
solve();
return 0;
}


举报

相关推荐

0 条评论