思路
普通 BFS 不能处理带权格子,Dijkstra 求的是最小代价,但这里多了 budget 限制。
如果只求最小代价,Dijkstra 可以;但要求"在不超过 budget 的前提下最小代价",其实仍然可以先求最小代价,再判断是否 ≤ budget。
不过因为可以上下左右走,且代价非负,所以可以用 Dijkstra。
如果代价可能为 0,Dijkstra 仍然适用。
如果要求"是否存在路径总代价 ≤ budget",也可以 Dijkstra 后判断。
代码
c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAXM 205
#define MAXN 205
#define INF 0x3f3f3f3f
typedef struct {
int x, y, dist;
} Node;
int m, n;
int cost[MAXM][MAXN];
int dist[MAXM][MAXN];
int visited[MAXM][MAXN];
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
typedef struct {
Node data[MAXM * MAXN * 4];
int size;
} Heap;
void push(Heap *h, Node v) {
int i = ++h->size;
while (i > 1 && h->data[i / 2].dist > v.dist) {
h->data[i] = h->data[i / 2];
i /= 2;
}
h->data[i] = v;
}
Node pop(Heap *h) {
Node res = h->data[1];
Node last = h->data[h->size--];
int i = 1, child;
while (i * 2 <= h->size) {
child = i * 2;
if (child < h->size && h->data[child + 1].dist < h->data[child].dist)
child++;
if (last.dist <= h->data[child].dist) break;
h->data[i] = h->data[child];
i = child;
}
h->data[i] = last;
return res;
}
int main() {
int budget;
scanf("%d %d", &m, &n);
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
scanf("%d", &cost[i][j]);
scanf("%d", &budget);
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
dist[i][j] = INF;
Heap h;
h.size = 0;
dist[0][0] = cost[0][0];
push(&h, (Node){0, 0, dist[0][0]});
while (h.size > 0) {
Node cur = pop(&h);
int x = cur.x, y = cur.y;
if (visited[x][y]) continue;
visited[x][y] = 1;
for (int k = 0; k < 4; k++) {
int nx = x + dx[k];
int ny = y + dy[k];
if (nx < 0 || nx >= m || ny < 0 || ny >= n) continue;
int nd = cur.dist + cost[nx][ny];
if (nd < dist[nx][ny]) {
dist[nx][ny] = nd;
push(&h, (Node){nx, ny, nd});
}
}
}
if (dist[m - 1][n - 1] <= budget)
printf("%d\n", dist[m - 1][n - 1]);
else
printf("-1\n");
return 0;
}