[题目链接]
[算法]
首先 , 我们用f[u][k]表示现在在景点u ,还有k元钱 , 最多能够走多少路
不难发现f[u][k] = max{ f[v][k - P[u]] + Dist(u,v,min(C,ci)) } ( dist(u,v,w)表示从u走到v , 最多经过w条路 , 最多能走多少路 )
用倍增弗洛伊德求dist, 然后进行上述dp , 即可
时间复杂度 : O(N^4 + N^3logN + TlogQ)
[代码]
#include<bits/stdc++.h> using namespace std; const int inf = 1e9; #define MAXN 110 #define MAXLOG 20 int n,m,C,T,tot; int head[MAXN]; int a[MAXN],b[MAXN],p[MAXN],c[MAXN]; int dis[MAXN][MAXN],f[MAXN][MAXN * MAXN]; int mat[MAXLOG][MAXN][MAXN]; template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } int main() { read(n); read(m); read(C); read(T); for (int i = 1; i <= n; i++) { read(p[i]); read(c[i]); c[i] = min(c[i],C); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i != j) mat[0][i][j] = -inf; } } for (int i = 1; i <= m; i++) { int u,v,w; read(u); read(v); read(w); mat[0][u][v] = max(mat[0][u][v],w); } for (int i = 1; i < MAXLOG; i++) { memcpy(mat[i],mat[i - 1],sizeof(mat[i])); for (int k = 1; k <= n; k++) { for (int x = 1; x <= n; x++) { for (int y = 1; y <= n; y++) { if (mat[i - 1][x][k] != -inf && mat[i - 1][k][y] != -inf) mat[i][x][y] = max(mat[i][x][y],mat[i - 1][x][k] + mat[i - 1][k][y]); } } } } for (int i = 1; i <= n; i++) { for (int x = 1; x <= n; x++) a[x] = -inf; a[i] = 0; for (int k = 0; k < MAXLOG; k++) { if (c[i] & (1 << k)) { for (int x = 1; x <= n; x++) b[x] = -inf; for (int x = 1; x <= n; x++) { for (int y = 1; y <= n; y++) { b[y] = max(b[y],a[x] + mat[k][x][y]); } } memcpy(a,b,sizeof(a)); } } for (int j = 1; j <= n; j++) dis[i][j] = a[j]; } for (int i = 0; i <= n * n; i++) { for (int j = 1; j <= n; j++) { if (i < p[j]) { f[j][i] = 0; continue; } for (int k = 1; k <= n; k++) f[j][i] = max(f[j][i],f[k][i - p[j]] + dis[j][k]); } } while (T--) { int s,q,d; read(s); read(q); read(d); if (f[s][q] < d) { printf("-1 "); continue; } int l = 0 , r = q , mid , ans; while (l <= r) { mid = (l + r) >> 1; if (f[s][mid] >= d) { ans = mid; r = mid - 1; } else l = mid + 1; } printf("%d ",q - ans); } return 0; }