题目描述:
思路:首先最短路不一定边数最短,所以我们肯定要求出所有的情况取最小值,求出每一天的最短路,dis[day][n],类似于最短路的转移方法就行;
看到现场赛有人暴力dfs加剪枝过的,也是很厉害OVO
#include <bits/stdc++.h> using namespace std; const int maxn = 1000 + 7; int n, m, k; int ans = 0x3f3f3f3f; int mp[maxn][maxn], a[12]; bool vis[maxn]; void dfs(int now, int day, int sum) { if(day > k) return ; if(sum >= ans) return ; if(now == n) { ans = min(ans, sum); return ; } vis[now] = 1; for(int i = 1; i <= n; i++) { if(vis[i] || i == now) continue; dfs(i, day + 1, sum + mp[now][i] + a[day + 1]); } vis[now] = 0; } int main() { scanf("%d%d%d", &n, &m, &k); memset(mp, 0x3f, sizeof(mp)); for(int i = 1; i <= m; i++) { int u, v, cost; scanf("%d %d %d", &u, &v, &cost); mp[u][v] = mp[v][u] = min(mp[u][v], cost); } for(int i = 1; i <= k; i++) scanf("%d", a + i); dfs(1, 0, 0); if(ans >= 0x3f3f3f3f) puts("-1"); else printf("%lld\n", ans); return 0; }
#include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int N = 1010; const int M = 20010; int h[N], e[M], ne[M], w[M], idx; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } int q[N]; int dist[N][N]; int st[N]; int n, m, k; struct Node{ int u, day, w; bool operator < (const Node &A) const { return w > A.w; } }; void dijkstra(int fir) { memset(dist, 0x3f, sizeof dist); dist[0][fir] = 0; priority_queue<Node> que; que.push({fir, 0, 0}); while(!que.empty()) { Node t = que.top(); que.pop(); int u = t.u, d = t.day; if(t.w > dist[d][u]) continue; for(int i = h[u]; i != -1; i = ne[i]) { int v = e[i]; if(d + 1 <= k && dist[d + 1][v] > dist[d][u] + w[i] + q[d + 1]) { dist[d + 1][v] = dist[d][u] + w[i] + q[d + 1]; que.push({v, d + 1, dist[d + 1][v]}); } } } } int main() { memset(h, -1, sizeof h); scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c), add(b, a, c); } for(int i = 1; i <= k; i++) scanf("%d", &q[i]); dijkstra(1); int res = INF; for(int i = 1; i <= k; i++) res = min(res, dist[i][n]); if(res >= INF) res = -1; printf("%d\n", res); return 0; }