问题描述
小明因为受到大魔王的诅咒,被困到了一座荒无人烟的山上并无法脱离.这座山很奇怪: 这座山的底面是矩形的,而且矩形的每一小块都有一个特定的坐标(x,y)和一个高度H. 为了逃离这座山,小明必须找到大魔王,并消灭它以消除诅咒. 小明一开始有一个斗志值k,如果斗志为0则无法与大魔王战斗,也就意味着失败. 小明每一步都能从他现在的位置走到他的(N,E,S,W)四个位置中的一个,会消耗(abs(H1−H2))/k的体力,然后消耗一点斗志。 大魔王很强大,为了留下尽可能多的体力对付大魔王,小明需要找到一条消耗体力最少的路径. 你能帮助小明算出最少需要消耗的体力吗.
输入描述
第一行输入一个整数T(1≤T≤10) 接下来有T行T组数据,每组数据有三个整数n,m,k含义如题(1≤n,m≤50,0≤k≤50) 接下来有n行,每行m个字符,如果是数字则表示(i,j)的高度H(0≤H≤9),'#'表示障碍 最后两行分别输入小明的坐标(x1,y1)和大魔王的坐标(x2,y2),小明和魔王都不在障碍上。
输出描述
每组数据对应输出满足要求的体力(保留两位小数)。
如果无法逃离,则输出"No 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
dp[i][j][k]表示到达点(i, j)剩余斗志为k最小花费的体力值。
#include <cstdio> #include <queue> using namespace std; int n, m, k; int t; int x1, y1, x2, y2; char map[60][60]; double dp[60][60][60]; int dx[4] = {1, -1, 0, 0}; int dy[4] = {0, 0, 1, -1}; const double inf = 1e9; struct node { node() {}; node(int a, int b, int c) : x(a), y(b), p(c) {} int x, y; int p; }; void solve() { queue <node> Q; Q.push(node(x1, y1, k)); dp[x1][y1][k] = 0; while (!Q.empty()) { node u = Q.front(); Q.pop(); int x = u.x, y = u.y; if (u.p <= 1 || (x == x2 && y == y2)) continue; int h1 = map[x][y] - '0'; for (int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; int h2 = map[nx][ny] - '0'; if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && map[nx][ny] != '#') { int nh = h2 - h1; if (nh < 0) nh = -nh; double cost = 1.0 * nh / u.p; if (dp[x][y][u.p] + cost < dp[nx][ny][u.p - 1]) { dp[nx][ny][u.p - 1] = dp[x][y][u.p] + cost; Q.push(node(nx, ny, u.p - 1)); } } } } } int main() { scanf("%d", &t); while(t--) { scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; i++) { getchar(); for (int j = 1; j <= m; j++) { scanf("%c", &map[i][j]); for (int a = 0; a <= k; a++) dp[i][j][a] = inf; } } scanf("%d%d", &x1, &y1); scanf("%d%d", &x2, &y2); solve(); double ans = inf; for (int i = 1; i <= k; i++) ans = min(dp[x2][y2][i], ans); if (ans == inf) printf("No Answer\n"); else printf("%.2lf\n", ans); } return 0; }