题目描述
有宽度不超过 100 的正方形迷宫如下所示:
K . S # # 1 1 # T “K”代表开始孙悟空所处的位置,“T”代表唐僧所处的位置,“.”代表空地,“#”代表墙,“S”代表此处有一条蛇,数字 nnn 代表此处有钥匙且要是的种类编号是 nnn(0<n≤90 \lt n \le 90<n≤9)。孙悟空要去救唐僧,他只能朝上、下、左、由四个方向走,走到相邻的格子需要花 1min1 min1min。“#”处不能走。走到“S”处则需要停留 1min1 min1min。走到放钥匙处,如果钥匙的种类编号为 nnn,且孙悟空已经得到了编号为 1,2........n−1 的钥匙,则它可以取走该钥匙,否则就只能过而不取。一共有 m 种钥匙(0<m≤90 \lt m \le 90<m≤9),孙悟空走到唐僧处时,必须集齐 mmm 种钥匙才能救唐僧,否则只能过而不救。问孙悟空要救唐僧,最少要花多长时间。
输入
输入包含多个测试样例。对于每个测试样例,第一行包含两个整数 n和 m(0<n≤1000 ,0<m≤90 ),随后输入一个 n*n 的矩阵。当输入的样例为 n=0 和 m=0 时,输入终止。
输出
对于每行测试样例,输出孙悟空救唐僧所需要的最短时间(以分钟为单位)。如果孙悟空无法完成该任务,则输出“impossible”。
输入输出样例
样例输入 #1
这个需要分层次来写每一个不同的钥匙为一层,同时最短路径广搜,然后你需要判断一下步数和钥匙的数量当步数不同的时候肯定小的优先,相同时看钥匙大的优先你需要用到优先队列
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
char a[105][105];
int vis[105][105][105];
int n,m;
int row1, line1;
int b[4] = { 0,0,1,-1 };
int c[4] = { 1,-1,0,0 };
bool flag;
struct node
{
int row;
int line;
int step;
int k;
friend bool operator < (node a, node b)
{
if (a.step != b.step)
return a.step > b.step;
return a.k < b.k;
}
};
priority_queue<node>r;
int main()
{
while (cin >> n >> m)
{
if (n == 0 && m == 0)
break;
flag = false;
memset(vis,0, sizeof(vis));
memset(a, '.', sizeof(a));
while (!r.empty())
{
r.pop();
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> a[i][j];
if (a[i][j] == 'T')
{
row1 = i;
line1 = j;
}
if (a[i][j] == 'K')
{
node start;
start.row = i;
start.line = j;
start.step = 0;
start.k = 0;
vis[i][j][start.k] = 1;
r.push(start);
}
}
}
while (!r.empty())
{
if (r.top().row == row1 && r.top().line == line1&&r.top().k==m)
{
flag = true;
cout << r.top().step << endl;
break;
}
for (int i = 0; i < 4; i++)
{
int xx = r.top().row + b[i];
int yy = r.top().line + c[i];
if (vis[xx][yy][r.top().k] == 0 && a[xx][yy] != '#' && xx >= 0 && xx < n && yy>=0 && yy < n)
{
node temp;
if (a[xx][yy] == '.')
{
vis[xx][yy][r.top().k] = 1;
temp.row = xx;
temp.line = yy;
temp.k = r.top().k;
temp.step = r.top().step + 1;
r.push(temp);
}
else if (a[xx][yy] == 'S')
{
vis[xx][yy][r.top().k] = 1;
temp.row = xx;
temp.line = yy;
temp.k = r.top().k;
temp.step = r.top().step + 2;
r.push(temp);
}
else if (a[xx][yy] == 'T')
{
vis[xx][yy][r.top().k] = 1;
temp.row = xx;
temp.line = yy;
temp.k = r.top().k;
temp.step = r.top().step + 1;
r.push(temp);
}
else
{
vis[xx][yy][r.top().k] = 1;
int b = a[xx][yy] - '0';
temp.row = xx;
temp.line = yy;
temp.step = r.top().step + 1;
if (b == r.top().k + 1)
{
temp.k = b;
}
else
{
temp.k = r.top().k;
}
r.push(temp);
}
}
}
r.pop();
}
if (!flag)
cout << "impossible" << endl;
}
}
3 1
K . S
# # 1
1 # T
3 1
K # T
. S #
1 # .
3 2
K # T
. S .
2 1 .
0 0
样例输出 #1
复制
5
impossible