[UVa 816] Abbott 的复仇(Abbott's Revenge)

Judge:https://vjudge.net/problem/UVA-816
题意:一个迷宫,每个点限制了从哪一方向(东西南北)来的,只能往左右前走,然后问起点到终点的最短路径。


比较难的一道迷宫题,要保存每个点所能走的方向。

特别注意的一点,路径可能有环形,这会影响到输出。

#include <iostream>
#include <string>
#include <cstdio>
#include <queue>
using namespace std;

#define DIR_EAST	0
#define DIR_NORTH	1
#define DIR_WEST	2
#define DIR_SOUTH	3

const char c_strDir[5] = "ENWS";
const int c_iX[4] = { 1, 0, -1, 0 };
const int c_iY[4] = { 0, -1, 0, 1 };

struct SPoint {
	SPoint() : x(0), y(0), iDir(0) {}
	SPoint(int iInX, int iInY, int iInDir) : x(iInX), y(iInY), iDir(iInDir) {}
	
	int x, y;
	int iDir;
	
	bool operator == (int i) { if (i == 0) return x == 0 && y == 0; }
	bool operator == (SPoint ptB) { return x == ptB.x && y == ptB.y; }
};

// [y][x][Direction][Turn]
bool g_arrMap[10][10][4][4];
SPoint g_arrPrev[10][10][4];

int GetDirection(char chDir)
{
	for (int i = 1; i <= 4; i++)
		if (c_strDir[i - 1] == chDir)
			return i - 1;
	return -1;
}

int TurnToDir(int iDir, char chTurn)
{
	if (chTurn == 'L')
		return (iDir + 1) % 4;
	else if (chTurn == 'R')
		return (iDir + 4 - 1) % 4;
	else
		return iDir;
}

SPoint GetNextStep(SPoint pt, int iDir)
{
	return SPoint(pt.x + c_iX[iDir], pt.y + c_iY[iDir], iDir);
}

SPoint Search(SPoint ptStart, SPoint ptEnd)
{
	SPoint pt = GetNextStep(ptStart, ptStart.iDir), ptNext;
	g_arrPrev[pt.y][pt.x][pt.iDir] = ptStart;
	
	queue<SPoint> theQueue;
	theQueue.push(pt);
	while (!theQueue.empty())
	{
		pt = theQueue.front();
		theQueue.pop();
		
		if (pt == ptEnd)
			return pt;
		
		for (int i = 0; i <= 3; i++)
		{
			if (g_arrMap[pt.y][pt.x][pt.iDir][i])
			{
				ptNext = GetNextStep(pt, i);
				if (ptNext.y >= 1 && ptNext.y <= 9 &&
					ptNext.x >= 1 && ptNext.x <= 9 &&
					g_arrPrev[ptNext.y][ptNext.x][ptNext.iDir] == 0)
				{
					g_arrPrev[ptNext.y][ptNext.x][ptNext.iDir] = pt;
					theQueue.push(ptNext);
				}
			}
		}
	}
	
	return SPoint(-1, -1, -1);
}

int g_iPrintCnt = 0;
void Print(SPoint pt)
{
	if (pt == SPoint(-1, -1, -1))
	{
		cout << "  No Solution Possible";
		cout << endl;
		return;
	}
	
	if (!(g_arrPrev[pt.y][pt.x][pt.iDir] == 0))
	{
		SPoint ptNext = g_arrPrev[pt.y][pt.x][pt.iDir];
		g_arrPrev[pt.y][pt.x][pt.iDir] = SPoint(0, 0, 0);
		Print(ptNext);
	}
	
	if (!g_iPrintCnt)
		cout << " ";
	g_iPrintCnt++;
	printf(" (%d,%d)", pt.y, pt.x);
	if (g_iPrintCnt == 10)
	{
		g_iPrintCnt = 0;
		cout << endl;
	}
}

#define DEBUG

int main()
{
	#ifndef DEBUG
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif

	string strTitle;
	SPoint ptStart, ptEnd;
	
	while (cin >> strTitle, strTitle != "END")
	{
		for (int i = 0; i < 10; i++)
			for (int j = 0; j < 10; j++)
				for (int m = 0; m < 4; m++)
					for (int n = 0; n < 4; n++)
						g_arrMap[i][j][m][n] = 0;
		for (int i = 0; i < 10; i++)
			for (int j = 0; j < 10; j++)
				for (int m = 0; m < 4; m++)
					g_arrPrev[i][j][m] = SPoint(0, 0, 0);
		g_iPrintCnt = 0;
		
		cin >> ptStart.y >> ptStart.x;
		char chTmp;
		cin >> chTmp;
		cin >> ptEnd.y >> ptEnd.x;
		ptStart.iDir = GetDirection(chTmp);
		
		SPoint ptTmp;
		while (cin >> ptTmp.y, ptTmp.y)
		{
			cin >> ptTmp.x;
			
			char chDir, iDir, chTurn;
			getchar();
			while (chDir = getchar(), chDir != '*')
			{
				iDir = GetDirection(chDir);
				while (chTurn = getchar(), chTurn != ' ')
					g_arrMap[ptTmp.y][ptTmp.x][iDir][TurnToDir(iDir, chTurn)] = true;
			}
		}
		
		cout << strTitle << endl;
		Print(Search(ptStart, ptEnd));
		if (g_iPrintCnt)
			cout << endl;
	}
	
	#ifndef DEBUG
		fclose(stdin);
		fclose(stdout);
	#endif
	
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值