Ural1060 (数位+bfs)

1060. Flip Game

Time limit: 2.0 second
Memory limit: 64 MB
Flip game is played on a rectangular 4×4 field withtwo-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying either it's black or white side up. Each roundyou flip 3 to 5 pieces, thus changing the color of theirupper side from black to white and vice versa. The piecesto be flipped are chosen every round according to thefollowing rules:
  1. Choose any one of the 16 pieces.
  2. Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
Problem illustration
Consider the following position as an example:
bwbw
wwww
bbwb
bwwb
Here "b" denotes pieces lying their black side up and "w"denotes pieces lying their white side up. If we choose to flipthe 1st piece from the 3rd row (this choice is shown at the picture),then the field will become:
bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up orall pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.

Input

The input consists of 4 lines with 4 characters "w" or "b" each that denote game field position.

Output

Write to the output a single integer number — the minimum number of rounds needed to achieve the goal of the game from the given position. If the goal is initially achieved, then write 0. If it's impossible to achieve the goal, then write the word "Impossible" (without quotes).

Sample

inputoutput
bwbw
wwww
bbwb
bwwb
Impossible

题意很简单就是翻转棋子,最后能否达到目标全白全黑的状态。经典题啊,和poj1753是同样的题。

思路:
 这里用的算法也是被广为流传的算法辣。。。
只有16个格子,那么用二进制的每一位代表一个棋子,一个16位的整数就可以代表一个棋盘的状态辣,目标状态p=0 || p=65535
 15 14 13 12
 11 10  9   8
  7   6   5   4 
  3   2   1   0
16个位置的标号分别列出,如100100111100,0000 ,代表从高位到低位。每个棋子只能翻转一次,因为只有两种状态,如果翻转两次等于没翻转。那么整个过程最多也就走16步,如果超过16还没达到目标状态,那就铁定达不到辣。输入初始状态,然后bfs 搜索,看是否能在16步之内达到目标状态。
 本人搜索很弱,虽然搜索是最最基本的,但是。。。。渣渣啊。。


AC代码
// 题意4*4的棋盘,给出初始状态,问能否达到全0,或者全1状态,每翻转一个棋子
// 周围的四个都要翻转。
// 思路:因为只有0,1 状态,所以每个棋子只能翻转一次,否则就没意义了
//那么最多就走16步,翻转16次辣  这里用二进制数位表示棋盘的状态 结果状态为 0 或者65536  ,bfs


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using  namespace std;
char map[6][6];
int vis[66000];
struct Node
{
	int s;
	int t; //表示当前的状态和走过的步数 ,方便bfs bfs计算从初始状态到目标状态的步数  
}P;

int Flip(int a,int i) //翻转操作 
{
	a^=(1<<i); //改变当前位
	if(i+4<16) a^=(1<<(i+4));// up  最上面一排不能再+4  
	if(i>3) a^=(1<<(i-4));   //down 最下面一排不能再-4 
	if((i%4)<3 && i+1<16 ) a^=(1<<(i+1));// right 最左边一列不能再+1  
	if((i%4)>0 && i-1>=0 ) a^=(1<<(i-1));// left 最右边一列不能再-1 
	
	return a;  
}

int bfs(int a)
{
	if(a==0 || a==65535)return 0;
	Node f,tmp;
	queue<Node> q;
	f.s=a;f.t=0;
    q.push(f);
    
	while(!q.empty())
	{
		tmp=q.front();
		q.pop();
		for(int i=0;i<16;i++)
		{
			f.s=Flip(tmp.s,i);f.t=tmp.t+1;
			
			if(f.s==0 || f.s==65535)
			{
				return f.t;
			}
			if(!vis[f.s])
			{
				vis[f.s]=1;
				q.push(f);
				
			}
		}
	}
	return -1;
}
int main()
{
	//freopen("q.in","r",stdin);
	int i,j;
	int p=0; //初始化的状态  
	memset(vis,0,sizeof(vis));
	for(i=0;i<4;i++)
	{
		scanf("%s",&map[i]);
		for(j=0;j<4;j++)
		{
			if(map[i][j]=='b') // black 用表示 
			{
				p=p|(1<<(i*4+j));
			}
		} 
		//getchar();
	}
	vis[p]=1;
	int ans=bfs(p);
	
	if(ans==-1)
	 cout<<"Impossible"<<endl;
	else cout<<ans<<endl;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值