题意
题目的大概意思是讲有一个迷宫游戏,给出其布局,和一个最佳行走路线,要求判断这个最佳路线是否是唯一的最短路线。同时,如果有多余(不影响结果)的墙也不行。
分析
我们来考虑每一面墙的作用,假如这面墙是必要的(拆了影响结果)。那么从这面墙到起点的距离加上到终点的距离必然小于给出的最佳路线长度。
所以,可以分别从起点和终点出发,假定给出的最佳路线长度为n,那么从起点和终点分别走n步(广度搜索),得到距离起点和终点n步的范围。然后再计算一下每一面墙分别到起点和终点的距离之和,如果一面墙的任意一面不在n步范围之内,显然这面墙是没有必要的。当然,如果距离之和大于最佳路线,也是没有必要的。
至于是不是唯一路线,从起点到终点广度搜索一遍即可确定。
代码如下:
Memory: 252K Time: 16MS Length: 178LINES
#include<iostream>
#include<string>
using namespace std;
struct PointPair { int x1, y1, x2, y2; };
struct PointandPath
{
int x, y;
string curpath;
PointandPath* next;
PointandPath(int a, int b, string s)
{ x = a; y = b; curpath = s; next = NULL; }
};
struct DirectionSet { bool up, right, down, left; };
int width, height;
string path;
int walls;
int* stepmatrix;
int* stepmatrix2;
DirectionSet* map_direction;
int endx = 0, endy = 0;
PointPair* wallcoor;
string bestpath;
bool* visit;
void BuildMap()
{
for (int i = 0; i < width; ++i)
map_direction[i * height].down = map_direction[i * height + height - 1].up = false;
for (int i = 0; i < height; ++i)
map_direction[i].left = map_direction[(width - 1) * height + i].right = false;
int count = 0;
while (count < walls)
{
if (wallcoor[count].x1 < wallcoor[count].x2)
map_direction[wallcoor[count].x1 * height + wallcoor[count].y1].right = map_direction[wallcoor[count].x2 * height + wallcoor[count].y2].left = false;
else if (wallcoor[count].x2 < wallcoor[count].x1)
map_direction[wallcoor[count].x2 * height + wallcoor[count].y2].right = map_direction[wallcoor[count].x1 * height + wallcoor[count].y1].left = false;
else if (wallcoor[count].y1 < wallcoor[count].y2)
map_direction[wallcoor[count].x1 * height + wallcoor[count].y1].up = map_direction[wallcoor[count].x2 * height + wallcoor[count].y2].down = false;
else if (wallcoor[count].y2 < wallcoor[count].y1)
map_direction[wallcoor[count].x1 * height + wallcoor[count].y1].down = map_direction[wallcoor[count].x2 * height + wallcoor[count].y2].up = false;
++count;
}
}
void Traverse(int x, int y, const int dx, const int dy, int& count, int* matrix)
{
memset(visit, true, sizeof(bool) * width * height);
PointandPath* head = new PointandPath(x, y, "");
PointandPath* rear = head;
visit[x * height + y] = false;
while (head)
{
if (head->x == dx && head->y == dy)
{
if (bestpath.length() == 0 || bestpath.length() > head->curpath.length())
{
bestpath = head->curpath;
count = 1;
}
else if (head->curpath.length() == bestpath.length() && head->curpath != bestpath)
++count;
}
matrix[head->x * height + head->y] = head->curpath.length();
if (map_direction[head->x * height + head->y].right && visit[(head->x + 1) * height + head->y] &&
(head->curpath.length() + 1 <= matrix[(head->x + 1) * height + head->y] || matrix[(head->x + 1) * height + head->y] == 0) &&
head->curpath.length() + 1 <= path.length())
{
rear = rear->next = new PointandPath(head->x + 1, head->y, head->curpath + 'R');
visit[(head->x + 1) * height + head->y] = false;
}
if (map_direction[head->x * height + head->y].left && visit[(head->x - 1) * height + head->y] &&
(head->curpath.length() + 1 <= matrix[(head->x - 1) * height + head->y] || matrix[(head->x - 1) * height + head->y] == 0) &&
head->curpath.length() + 1 <= path.length())
{
rear = rear->next = new PointandPath(head->x - 1, head->y, head->curpath + 'L');
visit[(head->x - 1) * height + head->y] = false;
}
if (map_direction[head->x * height + head->y].up && visit[head->x * height + head->y + 1] &&
(head->curpath.length() + 1 <= matrix[head->x * height + head->y + 1] || matrix[head->x * height + head->y + 1] == 0) &&
head->curpath.length() + 1 <= path.length())
{
rear = rear->next = new PointandPath(head->x, head->y + 1, head->curpath + 'U');
visit[head->x * height + head->y + 1] = false;
}
if (map_direction[head->x * height + head->y].down && visit[head->x * height + head->y - 1] &&
(head->curpath.length() + 1 <= matrix[head->x * height + head->y - 1] || matrix[head->x * height + head->y - 1] == 0) &&
head->curpath.length() + 1 <= path.length())
{
rear = rear->next = new PointandPath(head->x, head->y - 1, head->curpath + 'D');
visit[head->x * height + head->y - 1] = false;
}
PointandPath* p = head;
head = head->next;
delete p;
}
}
inline bool AtStartorEnd(int x, int y)
{
if ((x == 0 && y == 0) || (x == endx && y == endy))
return true;
else
return false;
}
int shorter(int pos)
{
int tmp1 = 0, tmp2 = 0;
if ((stepmatrix[wallcoor[pos].x1 * height + wallcoor[pos].y1] != 0 || AtStartorEnd(wallcoor[pos].x1, wallcoor[pos].y1)) &&
(stepmatrix2[wallcoor[pos].x2 * height + wallcoor[pos].y2] != 0 || AtStartorEnd(wallcoor[pos].x2, wallcoor[pos].y2)))
tmp1 = stepmatrix[wallcoor[pos].x1 * height + wallcoor[pos].y1] + stepmatrix2[wallcoor[pos].x2 * height + wallcoor[pos].y2];
if ((stepmatrix[wallcoor[pos].x2 * height + wallcoor[pos].y2] != 0 || AtStartorEnd(wallcoor[pos].x2, wallcoor[pos].y2)) &&
(stepmatrix2[wallcoor[pos].x1 * height + wallcoor[pos].y1] != 0 || AtStartorEnd(wallcoor[pos].x1, wallcoor[pos].y1)))
tmp2 = stepmatrix[wallcoor[pos].x2 * height + wallcoor[pos].y2] + stepmatrix2[wallcoor[pos].x1 * height + wallcoor[pos].y1];
if (tmp1 == 0) return tmp2 == 0 ? 0 : tmp2 + 1;
if (tmp2 == 0) return tmp1 == 0 ? 0 : tmp1 + 1;
else return tmp1 < tmp2 ? tmp1 + 1 : tmp2 + 1;
}
int main()
{
int cases;
cin >> cases;
while (cases-- > 0)
{
cin >> width >> height >> path >> walls;
endx = 0;
endy = 0;
wallcoor = new PointPair[walls];
stepmatrix = new int[height * width];
stepmatrix2 = new int[height * width];
visit = new bool[height * width];
map_direction = new DirectionSet[height * width];
memset(stepmatrix, 0, sizeof(int) * height * width);
memset(stepmatrix2, 0, sizeof(int) * height * width);
memset(wallcoor, 0, sizeof(PointPair) * walls);
memset(map_direction, true, sizeof(DirectionSet) * height * width);
for (int i = 0; i < walls; ++i)
cin >> wallcoor[i].x1 >> wallcoor[i].y1 >> wallcoor[i].x2 >> wallcoor[i].y2;
BuildMap();
int key = 0;
stepmatrix2[0] = path.length();
while (key < path.length())
{
if (path[key] == 'R') { if (map_direction[endx * height + endy].right) ++endx; else break; }
else if (path[key] == 'U') { if (map_direction[endx * height + endy].up) ++endy; else break; }
else if (path[key] == 'L') { if (map_direction[endx * height + endy].left) --endx; else break; }
else if (path[key] == 'D') { if (map_direction[endx * height + endy].down) --endy; else break; }
stepmatrix[endx * height + endy] = ++key;
stepmatrix2[endx * height + endy] = path.length() - key;
}
if (key == path.length())
{
int count = 0;
bestpath = "";
Traverse(0, 0, endx, endy, count, stepmatrix);
if (count == 1 && bestpath == path)
{
Traverse(endx, endy, 0, 0, count, stepmatrix2);
int i = 0;
while (i < walls)
{
int length = shorter(i++);
if (length > path.length() || length == 0)
{
cout << "INCORRECT" << endl;
break;
}
}
if (i == walls) cout << "CORRECT" << endl;
}
else cout << "INCORRECT" << endl;
}
else cout << "INCORRECT" << endl;
delete[] wallcoor;
delete[] stepmatrix;
delete[] stepmatrix2;
delete[] map_direction;
delete[] visit;
}
return 0;
}