UVa 589 - Pushing Boxes

题目:二维推箱子游戏,给你箱子、人和目标的位置,输出问题的解(推箱子和行走的路径)。

分析:搜索、优先队列。优先顺序为:首先保证推箱子的字数最少、然后是走的步数最少。

利用二叉堆做优先队列,在上面进行bfs即可。

说明:注意搜索时按照字典序方向枚举,不然会WA╮(╯▽╰)╭。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

char maps[20][21];

typedef struct node0
{
	int  X,Y,x,y;
	int  front,push,move,id;
	char step;
}dnode;
dnode H[160001];
dnode Q[160001];
bool  U[20][20][20][20];
int   dxy[4][2] = {0,1,-1,0,1,0,0,-1};
char  O[5] = "ENSW",o[5] = "ensw";
int   q_size;

//banery_heap define
int bh_size; 

void bh_init()
{
	bh_size = 0;
}

int bh_empty()
{
	return bh_size == 0;
}

bool bh_cmp(dnode a, dnode b)
{
	if (a.push != b.push)
		return a.push < b.push;
	return a.move < b.move;
}

void bh_insert(dnode s)
{
	H[++ bh_size] = s;
	int now = bh_size;
	while (now > 1 && bh_cmp(H[now], H[now>>1])) {
		swap(H[now], H[now>>1]);
		now = now>>1;
	}
}

dnode bh_delete(void)
{
	swap(H[bh_size], H[1]);
	int now = 1;
	while (1) {
		int New = now,L = (now<<1),R = (now<<1)+1;
		if (L < bh_size && bh_cmp(H[L], H[New])) New = L;
		if (R < bh_size && bh_cmp(H[R], H[New])) New = R;
		if (now == New) break;
		swap(H[now], H[New]);
		now = New;
	}
	return H[bh_size --];
}
//banery_heap end

void output(dnode s)
{
	if (s.front) {
		output(Q[s.front]);
		printf("%c",s.step);
	}else printf("%c",s.step);
}

void bfs(dnode s, int n, int m)
{
	memset(U, 0, sizeof(U));
	U[s.X][s.Y][s.x][s.y] = 1;
	q_size = 0;

	bh_init();
	bh_insert(s);

	while (!bh_empty()) {
		dnode New,now = bh_delete();
		Q[q_size ++] = now;
		for (int k = 0 ; k < 4 ; ++ k) {
			New = now;
			New.x += dxy[k][0];
			New.y += dxy[k][1];
			New.front = q_size-1;
			if (New.x < 0 || New.x >= n || New.y < 0 || New.y >= m)
				continue;
			//推箱子
			if (New.X == New.x && New.Y == New.y) {
				New.X += dxy[k][0];
				New.Y += dxy[k][1];
				if (New.X < 0 || New.X >= n || New.Y < 0 || New.Y >= m)
					continue;
				if (maps[New.X][New.Y] != '#' && !U[New.X][New.Y][New.x][New.y]) {
					New.step = O[k];
					New.push ++;
					if (maps[New.X][New.Y] == 'T') {
						output(New);
						return;
					}
					U[New.X][New.Y][New.x][New.y] = 1;
					bh_insert(New);
				}
			}else if (maps[New.x][New.y] != '#' && !U[New.X][New.Y][New.x][New.y]) {
				New.step = o[k];
				New.move ++;
				U[New.X][New.Y][New.x][New.y] = 1;
				bh_insert(New);
			}
		}
	}
	printf("Impossible.");
}

int main()
{
	int n,m,t = 1;
	while (~scanf("%d%d",&n,&m) && n && m) {
		for (int i = 0 ; i < n ; ++ i)
			scanf("%s",maps[i]);

		dnode s;
		for (int i = 0 ; i < n ; ++ i)
		for (int j = 0 ; j < m ; ++ j) {
			if (maps[i][j] == 'S') {
				s.x = i; s.y = j;
			}
			if (maps[i][j] == 'B') {
				s.X = i; s.Y = j;
			}
		}

		printf("Maze #%d\n",t ++);
		bfs(s, n, m);
		printf("\n\n");
	}
    return 0;
}
时间: 2024-10-11 15:57:48

UVa 589 - Pushing Boxes的相关文章

【15.4.1 Pushing Boxes】双重bfs

[15.4.1 Pushing Boxes] 想象您正站在一个二维的迷宫中,迷宫由是正方形的方格组成,这些方格可能被岩石阻塞,也可能没有.您可以向北,南,东或西一步移到下一个方格.这些移动被称为行走(walk). 在一个空方格中放置了一个箱子,您可以挨着箱子站着,然后按这个方向推动这个箱子,这个箱子就可以被移动到一个临近的位置.这样的一个移动被称为推(push).除了推以外,箱子不可能用其他的方法被移动,这就意味着如果您把箱子推到一个角落,您就永远不能再把它从角落中推出. 一个空格被标识为目标空

poj 1475 Pushing Boxes

http://poj.org/problem?id=1475 Pushing Boxes Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4662   Accepted: 1608   Special Judge Description Imagine you are standing inside a two-dimensional maze composed of square cells which may or

HDU 1475 Pushing Boxes

Pushing Boxes Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on PKU. Original ID: 147564-bit integer IO format: %lld      Java class name: Main Special Judge Imagine you are standing inside a two-dimensional maze composed of sq

uva 103 Stacking Boxes(最长上升子序列)

Description  Stacking Boxes  Background Some concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when extended to arbitrary dimensions. Consider solving differential equations in several dimensions

UVa 103 Stacking Boxes --- DAG上的动态规划

UVa 103 题目大意:给定n个箱子,每个箱子有m个维度, 一个箱子可以嵌套在另一个箱子中当且仅当该箱子的所有的维度大小全部小于另一个箱子的相应维度, (注意箱子可以旋转,即箱子维度可以互换),求最多能套几个箱子. 第一行输入为n,m,之后是n行m维的箱子 解题思路:嵌套关系是二元关系,因此这题即在DAG上做动态规划, 只不过将二维的判断改成了n维,其他不变. 详细看考:DAG上的动态规划之嵌套矩形  (ps:这题可以理解成嵌套m边形) /* UVa 103 Stacking Boxes --

uva 103 Stacking Boxes (DAG)

uva 103 Stacking Boxes Background Some concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when extended to arbitrary dimensions. Consider solving differential equations in several dimensions and a

UVa 103 - Stacking Boxes (LIS,打印路径)

链接:UVa 103 题意:给n维图形,它们的边长是{d1,d2,d3...dn},  对于两个n维图形,求满足其中一个的所有边长 按照任意顺序都一一对应小于另一个的边长,这样的最长序列的个数,并且打印任意一个最长子串的路径, 例如:a(9,5,7,3),b(6,10,8,2),c(9,7,5,1),a和b不满足,但c和b满足 分析:首先对没组边长从小到大排序,再对各组图形按最小边排序,再求最大子串, 对于打印路径,可以逆序循环,也可递归求解 #include<cstdio> #include

UVA - 103 - Stacking Boxes (动态规划)

UVA - 103 Stacking Boxes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Background Some concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when

Pushing Boxes(广度优先搜索)

题目传送门 首先说明我这个代码和lyd的有点不同:可能更加复杂 既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径.但单单找到箱子的最短路肯定不行啊,因为有时候不能被推动,怎样确定一条既满足最短又满足可行的箱子路径呢,其实这就是一种有限制的BFS. 对于箱子: 设现在的位置为x,y,扩展方向为dx,dy,将要到达的下一个位置为x+dx,y+dy check它是否可行: 1.不越界. 2.之前没有走过. 3.不能走到“#”上. 4.人能够从当前站立的位置到达(