uva816 Abbott's Revenge (BFS+回溯)

题目大意

给你个迷宫,求最短路,不过在每个点转弯的方向受进入方向的限制

思路

确定好每个点的状态,再用bfd求出最短路,注意记得用个数组保存节点,以方便输出


事实上很多细节都是参考刘汝佳老师的,感觉非常巧妙

#include<cstdio>
#include<cstring>
#include<algorithm>
// #include<cmath> 由于后面用了的y1在cmath中已定义,所以必须放弃它 
#include<iostream>
#include<cstdlib>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<sstream>
#include<utility>
#include<ctype.h>
#define f(i, a, b) for(int i=a; i<b; i++)
#define rf(i, a, b) for(int i=a; i>=b; i--)
#define uf(i, a, b) for(i=a; i<b; i++)
#define urf(i, a, b) for(i=a; i>=b; i--)
#define cl(a, b) memset(a, b, sizeof(a))
#define pi acos(-1.0)
#define sm 1e-10
#define inf 1e9
#define inf64 1e16
#define ll long long
using namespace std;
typedef pair<int,int> Pair;

/* G++ 5.1.0 */

struct Node {
	int x, y, dir;
	Node (int x, int y, int dir) : //记得加=0,或后面加Node() {}; 也行 
		x(x), y(y), dir(dir) {};
	Node() {}; 
};

Node nod[10][10][4];
Pair beg, gol;
bool has_edge[10][10][4][3];
int p[10][10][4];

const char* dr1 = "NESW";
const char* dr2 = "FLR";

int dir_id  (char c) { return strchr(dr1, c)-dr1; }
int turn_id (char c) { return strchr(dr2, c)-dr2; }

int d1[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int x1, y1, sd;

bool read() {
	int x, y;
	char kase[22], dir0[2], dir1[5];
	scanf("%s", kase);
	if(!strcmp(kase, "END")) return false;
	scanf("%d%d%s%d%d", &beg.first, &beg.second, dir0, &gol.first, &gol.second);
	
	sd = dir_id(dir0[0]);
	x1 = beg.first+d1[sd][0];
	y1 = beg.second+d1[sd][1];
	
	cl(has_edge, false);
	while(scanf("%d", &x) && x) {
		scanf("%d", &y);
		for(;;) {
			scanf("%s", dir1);
			if(dir1[0]=='*') break;
			f(i, 1, strlen(dir1)) 
				has_edge[x][y][dir_id(dir1[0])][turn_id(dir1[i])] = true;
		}
	}
	printf("%s\n", kase);
	return true;
}

int print(Node end) {
	vector<Node> treenode;
	Node next = end;
	for(;;) {
		treenode.push_back(next);
		if(p[next.x][next.y][next.dir]==0) break;
		next = nod[next.x][next.y][next.dir];
	}
	treenode.push_back(Node(beg.first,beg.second,sd));
	
	int cnt2 = 0;
	for(int it = treenode.size()-1 ;it >= 0; it--) {
		Node pr = treenode[it];
		if(cnt2 % 10 == 0) printf(" ");
		printf(" (%d,%d)", pr.x, pr.y);
		if(++cnt2 % 10 == 0) printf("\n");
	}
	if(cnt2 % 10 != 0) printf("\n");
}

bool inter(int x, int y) {
	return x>=1 && x<=9 && y>=1 && y<=9;
}

int walk(int i, int rdir) {
	if(i==0) return rdir;
	if(i==2) return (rdir+1)%4;
	if(i==1) return (rdir+3)%4; 
}

void solve() {
	queue<Node> n;
	Node tree(x1, y1, sd);
	cl(p, -1);
	p[x1][y1][sd] = 0;
	n.push(tree);
	while(!n.empty()) {
		tree = n.front(); n.pop();
		int x=tree.x, y=tree.y, rdir=tree.dir;
		if(x==gol.first&&y==gol.second) {
			print(tree); return;
		}
		f(i, 0, 3) {
			int rt = walk(i, rdir);
			int rx = x+d1[rt][0], ry = y+d1[rt][1];
			if(inter(rx,ry)&&has_edge[x][y][rdir][i]&&p[rx][ry][rt]<0) {
				p[rx][ry][rt] = p[x][y][rdir] + 1;
				n.push(Node(rx,ry,rt));
				nod[rx][ry][rt] = tree;
			}
		}
	}
	printf("  No Solution Possible\n");
}

int main() {
	while(read()) {
		solve();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值