题目链接
小明因为受到大魔王的诅咒,被困到了一座荒无人烟的山上并无法脱离.这座山很奇怪: 这座山的底面是矩形的,而且矩形的每一小块都有一个特定的坐标(x,y)(x,y)(x,y)和一个高度HHH. 为了逃离这座山,小明必须找到大魔王,并消灭它以消除诅咒. 小明一开始有一个斗志值kkk,如果斗志为0则无法与大魔王战斗,也就意味着失败. 小明每一步都能从他现在的位置走到他的(N,E,S,W)(N,E,S,W)(N,E,S,W)四个位置中的一个,会消耗(abs(H1−H2))/k(abs(H_1-H_2))/k(abs(H1−H2))/k的体力,然后消耗一点斗志。 大魔王很强大,为了留下尽可能多的体力对付大魔王,小明需要找到一条消耗体力最少的路径. 你能帮助小明算出最少需要消耗的体力吗.
第一行输入一个整数T(1≤T≤10)T( 1 \leq T \leq 10 )T(1≤T≤10) 接下来有TTT行TTT组数据,每组数据有三个整数n,m,kn,m,kn,m,k含义如题(1≤n,m≤50,0≤k≤50)(1 \leq n,m \leq 50, 0 \leq k \leq 50)(1≤n,m≤50,0≤k≤50) 接下来有nnn行,每行mmm个字符,如果是数字则表示(i,j)(i,j)(i,j)的高度H(0≤H≤9)H(0 \leq H \leq 9)H(0≤H≤9),'#'表示障碍 最后两行分别输入小明的坐标(x1,y1)(x_1,y_1)(x1,y1)和大魔王的坐标(x2,y2)(x_2,y_2)(x2,y2),小明和魔王都不在障碍上。
每组数据对应输出满足要求的体力(保留两位小数)。 如果无法逃离,则输出"No AnswerNo \ AnswerNo Answer"
3
4 4 5
2134
2#23
2#22
2221
1 1
3 3
4 4 7
2134
2#23
2#22
2221
1 1
3 3
4 4 50
2#34
2#23
2#22
2#21
1 1
3 3
1.03
0.00
No Answer
优先队列+bfs
#include<stdio.h> #include<string.h> #include<math.h> #include<queue> #include<algorithm> using namespace std; const int f[4][2]={0,1,0,-1,1,0,-1,0}; double dis[52][52][52]; int n,m,K; int sx,sy,ex,ey; struct node { double d; int x,y,k; bool operator < (const node &b) const { return d>b.d; } }; char ma[52][52]; void bfs() { priority_queue<node> q; for(int i=0;i<n;i++) for(int j=0;j<m;j++) for(int l=0;l<=K;l++) dis[i][j][l]=1e9; node st,en; st.x=sx,st.y=sy,st.k=K; st.d=0.0; dis[sx][sy][K]=0.0; q.push(st); while(q.size()) { st=q.top(); q.pop(); for(int i=0;i<4;i++) { en.x=st.x+f[i][0]; en.y=st.y+f[i][1]; en.k=st.k-1; if(en.k<=0) continue; if(en.x>=0&&en.x<n&&en.y>=0&&en.y<m&&ma[en.x][en.y]!='#') { en.d=st.d+fabs((double)ma[en.x][en.y]-ma[st.x][st.y])/st.k; if(en.d<dis[en.x][en.y][en.k]) { dis[en.x][en.y][en.k]=en.d; q.push(en); } } } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&K); for(int i=0;i<n;i++) scanf("%s",ma[i]); scanf("%d%d%d%d",&sx,&sy,&ex,&ey); sx--,sy--,ex--,ey--; bfs(); double ans=1e9; for(int i=1;i<=K;i++) ans=min(ans,dis[ex][ey][i]); if(ans>1e8) puts("No Answer"); else printf("%.2lf\n",ans); } return 0; }