题意:有一个W*H大小的迷宫,迷宫有两个出口,并且从迷宫中的每一个点都能够找到出口出去。求从迷宫中任意一点走出去的最优路线长度的最大值
解题思路:
- 读入W、H以及迷宫形状(用字符串数组maze[i][j]保存)
- 根据maze,用邻接表table[i][j]来表示这个迷宫。table[i][j] = k,代表节点i的第j个邻节点是k。并且在读取过程中保存两个出口所在的节点
- 对这两个出口节点进行Dijkstra,可以得到从出口到每一个节点的最短路径,分别保存为distance[i]和distance_cp[i]两个数组,distance[i] = j,代表从出口到i节点的最短路径长度为j
- 对distance和distance_cp两个数组遍历一遍即可得到最优线路的最大值
代码:
/*
ID: zc.rene1
LANG: C
PROG: maze1
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int W, H;
char **maze;
int **table;
int exits[2] = {0, 0};
int exits_count = 0;
int *distance = NULL;
int GetLeastUnvisited(int *visited, int *distance)
{
int i, ret = -1, least_distance = W*H;
for (i=0; i<W*H; i++)
{
if (visited[i] == 0)
{
if (distance[i] < least_distance)
{
ret = i;
least_distance = distance[i];
}
}
}
return ret;
}
void Dijkstra(int source)
{
int *visited;
int i, current_node, neighbour;
int temp, ret = 0;
visited = (int *)malloc(W*H*sizeof(int));
memset(visited, 0, W*H*sizeof(int));
for (i=0; i<W*H; i++)
{
distance[i] = W*H;
}
distance[source] = 0;
while ((current_node = GetLeastUnvisited(visited, distance)) != -1)
{
visited[current_node] = 1;
i = 0;
while ((neighbour = table[current_node][i]) != -1)
{
if (!visited[neighbour])
{
if ((distance[current_node] + 1) < distance[neighbour])
{
distance[neighbour] = distance[current_node] + 1;
}
}
i++;
if (i > 3)
{
break;
}
}
}
}
void InsertNeighbour(int add_i, int add_j, int addto_i, int addto_j)
{
int add = add_i * W + add_j;
int add_to = addto_i * W + addto_j;
int temp = 0;
if ((add_i < 0)||(add_i >= H))
{
exits[exits_count++] = add_to;
}
else if ((add_j < 0)||(add_j >= W))
{
exits[exits_count++] = add_to;
}
else
{
while (table[add_to][temp] != -1)
{
temp++;
}
table[add_to][temp] = add;
}
}
void AddNeighbour(int i, int j)
{
int room_i = 2 * i + 1;
int room_j = 2 * j + 1;
if (maze[room_i-1][room_j] == ' ')
{
InsertNeighbour(i-1, j, i, j);
}
if (maze[room_i+1][room_j] == ' ')
{
InsertNeighbour(i+1, j, i, j);
}
if (maze[room_i][room_j-1] == ' ')
{
InsertNeighbour(i, j-1, i, j);
}
if (maze[room_i][room_j+1] == ' ')
{
InsertNeighbour(i, j+1, i, j);
}
}
int main(void)
{
FILE *fin, *fout;
int i, j, temp, result = 0;
char c;
fin = fopen("maze1.in", "r");
fout = fopen("maze1.out", "w");
fscanf(fin, "%d %d", &W, &H);
table = (int **)malloc(W*H*sizeof(int*));
for (i=0; i<W*H; i++)
{
table[i] = (int *)malloc(4*sizeof(int));
memset(table[i], -1, 4*sizeof(int));
}
maze = (char **)malloc((2*H+1)*sizeof(char *));
for (i=0; i<2*H+1; i++)
{
maze[i] = (char *)malloc((2*W+1)*sizeof(char));
memset(maze[i], 0, (2*W+1)*sizeof(char));
}
fscanf(fin, "%c", &c);
for (i=0; i<2*H+1; i++)
{
for (j=0; j<2*W+1; j++)
{
fscanf(fin, "%c", &maze[i][j]);
}
fscanf(fin, "%c", &c);
}
for (i=0; i<H; i++)
{
for (j=0; j<W; j++)
{
AddNeighbour(i, j);
}
}
distance = (int *)malloc(W*H*sizeof(int));
Dijkstra(exits[0]);
int *distance_cp = (int *)malloc(W*H*sizeof(int));
memcpy(distance_cp, distance, W*H*sizeof(int));
Dijkstra(exits[1]);
for (i=0; i<W*H; i++)
{
temp = (distance[i] < distance_cp[i] ? distance[i] : distance_cp[i]);
if (temp > result)
{
result = temp;
}
}
fprintf(fout, "%d\n", result + 1);
return 0;
}