BFS POJ-1753&HDU-1429 状压BFS

状态压缩BFS

状态情况非常多,稍有改变影响多,此时我们通过二进制01串的方式进行状态压缩并广搜,来求解问题。

POJ-1753

Flip Game

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 51450   Accepted: 21720

Description

Flip game is played on a rectangular 4x4 field with two-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 round you flip 3 to 5 pieces, thus changing the color of their upper side from black to white and vice versa. The pieces to be flipped are chosen every round according to the following 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).


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 flip the 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 or all 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 file 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 Input

扫描二维码关注公众号,回复: 2543752 查看本文章
bwwb
bbwb
bwwb
bwww

Sample Output

4

题目大意:黑白棋翻转,翻转某一棋子,它上下左右的棋子也随之翻转,求至全黑或全白状态最少需要几步。

因为是4x4的棋盘,不算大,16个位置,状态压缩为2^16次方,设白为0黑为1,记录初始状态,并进行BFS,过程中有相应的解压过程。

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int maxc=1<<16;

int state;
int vst[maxc+10];

struct node{
	int num,step;
};

queue <node> q;

int change(int s,int i)
{
	s^=1<<i;
	if(i>3) s^=1<<i-4;
	if(i<12) s^=1<<i+4;
	if(i%4) s^=1<<i-1;
	if(i%4<3) s^=1<<i+1;
	return s;
}

int bfs()
{
	while(!q.empty())
		q.pop();

	node n,nextn;
	n.num=state;
	n.step=0;
	vst[state]=1;
	q.push(n);
	while(!q.empty()){
		n=q.front();
		q.pop();
		if(n.num==0||n.num==65535)
			return n.step;
		for(int i=0;i<16;++i){
			nextn.num=change(n.num,i);
			nextn.step=n.step+1;
			if(!vst[nextn.num]){
				vst[nextn.num]=1;
				q.push(nextn);
			}
		}
	}
	return -1;
}

int main()
{
	char c;

	state=0;
	memset(vst,0,sizeof(vst));
	for(int i=0;i<4;++i){
		for(int j=0;j<4;++j){
			scanf(" %c",&c);
			if(c=='b'){		//black 1 white 0
				state|=(1<<(i*4+j));
			}
		}
	}
	int ans=bfs();
	if(ans==-1)
		printf("Impossible\n");
	else
		printf("%d\n",ans);

	return 0;
}

HDU-1429

胜利大逃亡(续)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10810    Accepted Submission(s): 3930

 

Problem Description

Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……

这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。

 

Input

每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:

. 代表路
* 代表墙
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J

每组测试数据之间有一个空行。

 

Output

针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。

 

Sample Input

4 5 17

@A.B.

a*.*.

*..*^

c..b*

4 5 16

@A.B.

a*.*.

*..*^

c..b*

 

Sample Output

16

-1

 

分析:

相交传统简单的BFS迷宫题目多了一些钥匙和门,有些复杂难办,而让我们注意到钥匙的最大数量是10,足可以进行状态压缩,以10位01二进制串压缩为钥匙状态,vst数组状态也多了一维,因为当拿着钥匙的种类或数量不同时,是可以经过同一方格点的。

nextp.k=p.k|(1<<(v-'a')) 模拟取钥匙,将那一位钥匙由1置0

door=(1<<(v-'A')) 遇到的门   若(p.k&door)==door 模拟能否开门

然后就是愉快的BFS~(学弟太强了嘤!讲的好棒嘤!

#include <cstdio>
#include <cstring>
#include <queue>
#include <cctype>
using namespace std;

const int maxnm=20;

int n,m,t;
char g[maxnm+5][maxnm+5];
int vst[maxnm+5][maxnm+5][1030];
int sx,sy,ex,ey;
int flag,ans;
int dx[4]={1,0,-1,0},
	dy[4]={0,1,0,-1};

struct point{
	int x,y,k,step;
};

void bfs()
{
	point p,nextp;
	queue <point> q;

	p.x=sx;p.y=sy;
	p.k=0;
	p.step=0;
	vst[sx][sy][p.k]=1;
	q.push(p);
	while(!q.empty()){
		p=q.front();
		q.pop();
		for(int i=0;i<4;++i){
			nextp.x=p.x+dx[i];
			nextp.y=p.y+dy[i];
			nextp.step=p.step+1;
			char v=g[nextp.x][nextp.y];
			if(v=='.'||v=='@')
				nextp.k=p.k;
			else if(v=='^'){
				flag=1;
				ans=nextp.step;
				return;
			}
			else if(v=='*')
				continue;
			else if(islower(v))
				nextp.k=p.k|(1<<(v-'a'));
			else if(isupper(v)){
				int door=(1<<(v-'A'));
				if((p.k&door)==door)	//运算符优先级!&运算加括号!
					nextp.k=p.k;
				else continue;
			}
			if(!vst[nextp.x][nextp.y][nextp.k]){//printf("%d %d %c %d\n",nextp.x,nextp.y,v,nextp.k);
				vst[nextp.x][nextp.y][nextp.k]=1;
				q.push(nextp);
			}
		}
	}
}

int main()
{
	while(~scanf("%d%d%d",&n,&m,&t)){
		memset(vst,0,sizeof(vst));
		flag=ans=0;
		for(int i=0;i<=n+1;++i)
			g[i][0]=g[i][m+1]='*';
		for(int j=0;j<=m+1;++j)
			g[0][j]=g[n+1][j]='*';
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				scanf(" %c",&g[i][j]);
				if(g[i][j]=='@'){
					sx=i;sy=j;
				}
				else if(g[i][j]=='^'){
					ex=i;ey=j;
				}
			}
		}
		bfs();
		if(flag&&ans<t){
			printf("%d\n",ans);
		}
		else
			printf("-1\n");
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/DADDY_HONG/article/details/81394902
BFS
今日推荐