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;
}