UVA 314 Robot (BFS)

6 篇文章 0 订阅

题目大意:

有一个机器人走迷宫,每次可以走一格或者三格,然后中间有一些障碍不能走,这些障碍会挡住机器人。

题解:

无权图最短路径,优先考虑BFS,在这里我们知道,这个题目有一个关键的hints就是每个格子能走4个方向(分别对应机器人的四个朝向),为什么要区分能走4个方向,而不是平时的BFS只能走一次呢?因为这里的机器人不同朝向时,往下一步走的cost不一样!同一个方向走到某一格(r,c)的时候,假如从起点到(r,c)cost更低了,我们才接受这一步,否则放弃这一步。这有点DP的意思在里面。

废话:

因为,输入数据的变量(M,N)的命名搞反了,WA了5发,而且当形状是正方形或者路线刚好就在范围里面的话还真看不出来问题,真是深刻教训! 这告诉我们,调试的时候,有时候看不出来问题,真应该多打印一些简单的变量看看。同时,这题给我们的启发是,这种BFS similar的题,可以多考虑每一个节点的状态,是否允许重复走的问题!

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int N, M;
const int MAXR = 60;
const int MAXC = 60;
const int MAXD = 4;
int inrange(int r, int c) {
	return r >= 0 && r<M&&c >= 0 && c < N;
}
int main() {
	int n, m;
	while (cin >> m >> n && n&&m) {
		if (n<2 || m<2)while (1);
		N = n; M = m;
		int chess[MAXR][MAXC];
		memset(chess, 0, sizeof(chess));
		for (int i = 0; i<m; i++) {
			for (int j = 0; j<n; j++) {
				int t;
				cin >> t;
				int r = i - 1;
				int nxr = r + 1;
				int c = j - 1;
				int nxc = c + 1;
				if (t == 1) {
					if (inrange(r, c)) {
						chess[r][c] = 1;
					}
					if (inrange(r, nxc))chess[r][nxc] = 1;
					if (inrange(nxr, c))chess[nxr][c] = 1;
					if (inrange(nxr, nxc))chess[nxr][nxc] = 1;
				}
			}
		}
		int ur, uc, desr, desc; int udir;
		cin >> ur >> uc >> desr >> desc;
		ur -= 1;
		uc -= 1;
		desr -= 1;
		desc -= 1;
		string stmp;
		cin >> stmp;
		if (stmp[0] == 's') { udir = 2; }
		else if (stmp[0] == 'w')udir = 3;
		else if (stmp[0] == 'n')udir = 0;
		else if (stmp[0] == 'e')udir = 1;
		else assert(0);
		int dist[MAXR][MAXC][MAXD];
		if(chess[ur][uc]){
			cout<<-1<<endl;
			return 0;
		}
		memset(dist, INF, sizeof(dist));
		queue<pair<pair<int, int>, int>> q;
		q.push(make_pair(make_pair(ur, uc), udir));
		dist[ur][uc][udir] = 0;
		const int dr[] = { 0,0,0,-1,-2,-3,0,0,0,1,2,3 };
		const int dc[] = { -1,-2,-3,0,0,0,1,2,3,0,0,0 };
		const int ddir[] = { 3,3,3,0,0,0,1,1,1,2,2,2 };
		int par[MAXR*MAXC * 5];
		memset(par, 0, sizeof(par));
		while (!q.empty()) {
			int ur = q.front().first.first;
			int uc = q.front().first.second;
			int udir = q.front().second;
			q.pop();
			for (int i = 0; i<12; i++) {
				int nxr = ur + dr[i]; int nxc = uc + dc[i]; int nxdir = ddir[i];
				if (nxr<0 || nxr >= m - 1 || nxc<0 || nxc >= n - 1)continue;
				if (chess[nxr][nxc])continue;
				if (nxr - ur == 3 && chess[ur + 1][nxc])continue;
				if (nxr - ur == -3 && chess[ur - 1][nxc])continue;
				if (nxc - uc == 3 && chess[ur][uc + 1])continue;
				if (nxc - uc == -3 && chess[ur][uc - 1])continue;
				int turnCost = 0;
				if (udir == 1 || udir == 2)turnCost = abs(nxdir - udir);
				else if (udir == 3) {
					if (nxdir == 0 || nxdir == 2)turnCost = 1;
					else if (nxdir == udir)turnCost = 0;
					else turnCost = 2;

				}
				else {
					if (nxdir == 1 || nxdir == 3)turnCost = 1;
					else if (nxdir == udir) turnCost = 0;
					else turnCost = 2;
				}
				if (dist[ur][uc][udir] + turnCost + 1 <dist[nxr][nxc][nxdir]) {

					dist[nxr][nxc][nxdir] = dist[ur][uc][udir] + turnCost + 1;
					int no=encode(nxr, nxc, nxdir);
					par[no] = encode(ur, uc, udir);

					q.push(make_pair(make_pair(nxr, nxc), nxdir));
				}
			}
		}
		if (dist[desr][desc][0] == INF && dist[desr][desc][1] == INF&&dist[desr][desc][2] == INF&& dist[desr][desc][3] == INF) {
			cout << -1 << endl;
		}
		else {
			priority_queue<int, vector<int>, greater<int>> pq;
			for (int i = 0; i<4; i++)
			{
				pq.push(dist[desr][desc][i]);
			}
			cout << pq.top() << endl;
		}
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值