zoj 3478 Binary Land bfs

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3478

Binary Land



Time Limit: 2 Seconds      Memory Limit: 65536 KB



Binary Land is a very simple action title for the Famicom with an interesting twist. You control, not one, but two penguins, Gurin (male) and Malon (female), who are in love with each other. While you are in direct control of one penguin, you indirectly
control the other penguin, who moves in a mirror image fashion from the original penguin. When you move your penguin left, the other moves right, and vice versa. The goal of the game is to move both penguins from their own origins to the unique caged heart
at the same time.

At the beginning of each stage, you can choose which penguin to control directly. There are many walls which stop penguins from moving into them. If a penguin trys to do so, it will remain in the original grid. Besides the caged heart and walls, spider webs
are strewn about in the 10×15 maze. If one of the penguins hits the web, it will become stuck in place until the other penguin moves to its neighbour and helps the stuck penguin move from the spider web to its grid. This process costs 11 seconds. Generally,
it costs 5 seconds to move both penguins simultaneously. But when one of the penguins is stuck, moving the penguin which you directly control takes 2 seconds, while moving the other penguin takes 3 seconds.

What‘s the earliest time that Gurin and Malon can meet at the caged heart?

Binary Land Sample 1 Sample 2
Sample 3 Sample 4 Sample 5

Input

There are multiple test cases. The first line of input is an integer T ≈ 100 indicating the number of test cases.

Each test case contains 13 lines. The first 10 lines are the 10×15 maze, the 11th line is the origin of Gurin, the 12th line is the origin of Malon, and the 13th line is always a blank line. The maze is made up of unique caged heart (‘H‘), spider webs (‘O‘),
walls (‘X‘), and empty grids (‘.‘). The origins of penguins cannot be walls.

Output

For each test case, output the earliest time, or -1 when it‘s impossible.

Sample Input

5
.......H.......
.XXX.XXX.XXX.XX
XX.X.X.XXX.X.X.
..O....X.......
.XXXXX.X.XXXXX.
.......X....O..
XX.X.X.X.X.X.XX
.......X.......
.XXXXXXXXXXXXX.
.......X.......
1 15
1 1

.......H.......
.X.X.XXXXX.X.X.
.X.X.X.X.XXXXX.
...X..OX...X...
.XXX.XXXXX.X.XX
.......X.......
XX.XXX.X.XXXXX.
O..X...X.......
.X.X.X.XXX.X.XX
.....X.X.......
10 9
10 7

...XO..H.......
OX.X.X.X.X.X.XX
OXOX.XOX.X.X.X.
OX...X.XO..X..O
.XXXXXXX.XXX.XX
.O.XO..X..O....
.X.X.X.XXX.XXX.
OX.X.XOXO..X.O.
.XOX.X.X.X.X.X.
.X...X.X.....X.
10 9
10 7

.......H.....X.
.XXX.XXXXX.X.X.
XX.X.X.X.X.X.X.
.......XO..X...
.XXXXX.XXX.XXX.
.......X.X.....
.X.X.XXX.XXX.XX
.......X...X..O
XXXXXX.X.X.X.X.
.......X.X.....
1 10
1 4

.......H.......
.X.X.X.X.X.X.X.
.X.X.X.X.X.X.X.
.......X.......
.X.X.X.X.X.X.X.
.......X.......
.X.X.X.X.X.X.X.
.......X.......
.X.X.X.X.X.X.X.
......OX.......
10 1
10 7

Sample Output

35
140
-1
40
99

题意:给你地图‘X’是墙,‘.’是路,和两只公母企鹅的坐标,开始两只企鹅不会在墙里。他们如果没被困,或者没走到地图边缘,或者没被墙挡住,那么都是同步走的,上下同相走,左右反向走。求同时走到H点的最小时间。同时走耗时5s。图里有蜘蛛网‘O’,如果有一只被困,那么另一只可能是笨企鹅,也可能是聪明的企鹅,聪明的走一步耗时2s,笨的3s。如果一只企鹅走到另一只企鹅的旁边,可以把另一只救出来,让他到自己的位置。耗时11s。

两只企鹅如果都被困,就失败了。

做法:

bfs,因为不知道哪只是笨的,所以要bfs两次。打的比较麻烦,注意下各种情况就好了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define INF 999999999
#define eps 0.00001
#define LL __int64d
#define pi acos(-1.0)
// 10×15 maze, 

int dir[4][2][2]={
	1,0,
	1,0,

	-1,0,
	-1,0,

	0,1,
	0,-1,

	0,-1,
	0,1
};//一维四个方向 二维 哪只企鹅 三维xy
char mp[10][15];
int vis[10][15][10][15];//-1代表没走过, 不是-1代表到达这个状态最小花费的步数
struct point
{
	int x1,y1;
	int x2,y2;
	int bu;
	bool operator <(const point &b)const
	{
		return bu>b.bu;
	}
};

int ok(int x,int y)
{
	if(x>=0&&x<10&&y>=0&&y<15&&mp[x][y]!='X')
		return 1;
	return 0;
}

point walk(point nw,int t,int zou)//走,
{
	int xx1,xx2,yy1,yy2;

	if(zou&1)
	{
		xx1=nw.x1+dir[t][0][0];
		yy1=nw.y1+dir[t][0][1];
		if(ok(xx1,yy1))
		{
			nw.x1=xx1;
			nw.y1=yy1;
		}
	}

	if(zou&2)
	{
		xx2=nw.x2+dir[t][1][0];
		yy2=nw.y2+dir[t][1][1];

		if(ok(xx2,yy2))
		{
			nw.x2=xx2;
			nw.y2=yy2;
		}
	}
	return nw;
}

int low(point gg)
{
	if(vis[gg.x1][gg.y1][gg.x2][gg.y2]==-1||vis[gg.x1][gg.y1][gg.x2][gg.y2]>gg.bu)//判断能否更新vis,可以的话就走,return 1
	{
		vis[gg.x1][gg.y1][gg.x2][gg.y2]=gg.bu;
		return 1;
	}
	return 0;
}	

int near(point gg)//判断两只企鹅是否相邻
{
	if(abs(gg.x1-gg.x2)+abs(gg.y2-gg.y1)==1)
		return 1;
	return 0;
}

int bfs(point gg)
{
	priority_queue<point> q;
	gg.bu=0;
	q.push(gg);
	point nw;
	point tem;
	low(gg);
	while(!q.empty())
	{
		nw=q.top();
		q.pop();
		if(nw.x1==nw.x2&&nw.y1==nw.y2&&mp[nw.x1][nw.y1]=='H')//结束
			return nw.bu;
		if(mp[nw.x1][nw.y1]=='O'&&mp[nw.x2][nw.y2]=='O')//都被困
			continue;
		int xx1,xx2,yy1,yy2;

		if(mp[nw.x1][nw.y1]=='O') // 1被困
		{
			if(near(nw))//相邻,2 救1
			{
				tem=nw;
				tem.bu=nw.bu+11;
				tem.x1=tem.x2;
				tem.y1=tem.y2;
				if(low(tem))
					q.push(tem);
			}

			for(int i=0;i<4;i++)
			{
				tem=walk(nw,i,2);
				tem.bu=nw.bu+3;
				if(low(tem))
					q.push(tem);
			}
		}
		else if(mp[nw.x2][nw.y2]=='O') // 1hao 2s
		{
			if(near(nw))
			{
				tem=nw;
				tem.bu=nw.bu+11;
				tem.x2=tem.x1;
				tem.y2=tem.y1;
				if(low(tem))
					q.push(tem);
			}
			for(int i=0;i<4;i++)
			{
				tem=walk(nw,i,1);
				tem.bu=nw.bu+2;
				if(low(tem))
					q.push(tem);
			}
		}
		else
		{
			for(int i=0;i<4;i++)
			{
				tem=walk(nw,i,3);
				tem.bu=nw.bu+5;
				if(low(tem))
					q.push(tem);
			}
		}
	}
	return INF;
}

int main()
{

	int t;
	cin>>t;
	while(t--)
	{
		for(int i=0;i<10;i++)
		{
			scanf("%s",mp[i]);
		}
		memset(vis,-1,sizeof vis);

		point gg;
		cin>>gg.x1;
		gg.x1--;
		cin>>gg.y1;
		gg.y1--;
		cin>>gg.x2;
		gg.x2--;
		cin>>gg.y2;
		gg.y2--;

		int ans=bfs(gg);
		swap(gg.x1,gg.x2);
		swap(gg.y1,gg.y2);

		ans=min(ans,bfs(gg));

		if(ans==INF)
			cout<<"-1"<<endl;
		else
			cout<<ans<<endl;

	}
	return 0;
}
时间: 2024-09-28 15:57:02

zoj 3478 Binary Land bfs的相关文章

ZOJ - 2243 - Binary Search Heap Construction

先上题目: Binary Search Heap Construction Time Limit: 5 Seconds      Memory Limit: 32768 KB Read the statement of problem G for the definitions concerning trees. In the following we define the basic terminology of heaps. A heap is a tree whose internal n

Zoj 2913 Bus Pass BFS

题意: 给你一张图,和一些指定的点,找一个点使得这些指定的点到这个点的距离的最大值最小 对每一个指定的点都做一遍BFS,更新到达每个点的距离,取较大值,然后扫一遍所有的点,找出最小即可. 注意:不同于走格子,因为方向比较多,所以要在扩展节点的时候就更新vis数组,不然有可能导致某个点的距离因为重复更新而不是最小值. 并且不要漏了一开始就更新起点的vis #include <cstdio> #include <vector> #include <cstring> #inc

ZOJ - 3890 Wumpus(BFS基础题)

Wumpus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day Leon finds a very classic game called Wumpus.The game is as follow. Once an agent fell into a cave. The legend said that in this cave lived a kind of monster called Wumpus, and there we

ZOJ 3890 Wumpus (BFS)

题目链接:ZOJ 3890 Wumpus 题意:一个人在n*n的地图的左下角,他想逃出地图,并且他想要分数达到最高,他可以做的操作有直走,左转,右转,射击,爬,挖金矿6个操作,每个操作后分数减10,但是挖到金矿分数加1000,问你逃出地图的最大分数是多少.他可能遇到怪兽但是他不射击(也就是说没有射击的操作),金库在地图中也只有一个. 思路:BFS搜一遍就好了 AC代码: #include <stdio.h> #include <string.h> #include <queu

ZOJ 1107FatMouse and Cheese(BFS)

题目链接 分析: 一个n * n的图,每个点是一个奶酪的体积,从0,0开始每次最多可以走k步,下一步体积必须大于上一步,求最大体积和 1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 const int Max = 550 + 10; 8

Zoj 1671 Walking Ant(BFS+优先队列||记忆化搜索)

Walking Ant Time Limit: 2 Seconds Memory Limit: 65536 KB 点击打开链接 Ants are quite diligent. They sometimes build their nests beneath flagstones. Here, an ant is walking in a rectangular area tiled with square flagstones, seeking the only hole leading to

ZOJ 2655 Water Pipe bfs 带方向状态

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2655 Water Pipe Time Limit: 5 Seconds      Memory Limit: 32768 KB Two waterworks want to connect to each other with water pipes. Just as the map shows, the waterworks sit on two corners

ZOJ 3814 Sawtooth Puzzle BFS

感觉可以用BFS撸,然后就撸了,样例无限不过,代码能力真是弱.. #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <queue> using namespace std; const int bufsize = 128; char buf[bufsize][bufsize]; struct Block { char str[10][

ZOJ 3811 Untrusted Patrol bfs+并查集

题目链接:点击打开链接 题意: 给定n个点m条边的无向图,k个触发器. 下面k个数表示触发器安装在哪几个点. 下面m行给出边 最后有l个信号, 给出信号发出的触发器的顺序. 每个触发器只会发出一次信号,且一个点只有一个触发器. 有一个人在遍历图. 每经过一个点,那个点的触发器就会发出信号,问是否存在一种走法使得这个人遍历了所有点且触发器发出的信号顺序和给出的一样. 思路: 先把无触发器的点放到图里. 然后根据触发器的信号顺序把点依次加入图中,加入时只添加(与无触发器点相连的边) 然后判断这个点能