這題需要剪枝到達某個城市c的路徑有許多條,可能會有一些花的錢相同但路徑不同的路線。
也就是說 我們走到城市c只花了m1的錢,從另一條路走到c卻花了多餘m1的錢,
那麼這條路沒有必要繼續走下去,要麼到不了,要麼路徑長度和之前的路是一樣的,
總之不會小於那個花錢少的路線
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; int K, N, R; struct Road { int end, length, cost; }; vector<vector<Road> > city(105); const int INF = 1 << 30; int ans; int totalLen; int totalcost; bool vis[105]; int midL[105][10005];//midL[i][j] 表示 到達i城市時花費路費爲j所走的最短路徑 void dfs(int n) { if (n == N) { ans = min(ans, totalLen); return; } int size = city[n].size(); for (int i = 0; i < size; ++i) { int e = city[n][i].end; if (!vis[e]) { int cost = totalcost + city[n][i].cost; if (cost > K) continue; int len = totalLen + city[n][i].length; if (len >= ans || len >= midL[e][cost]) continue; totalcost = cost; totalLen = len; midL[e][cost] = len; vis[e] = true; dfs(e); vis[e] = false; totalLen -= city[n][i].length; totalcost -= city[n][i].cost; } } } int main() { freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); ios::sync_with_stdio(false); int s; Road t; while (cin >> K >> N >> R) { //memset(midL, INF, sizeof(midL)); for (int i = 0; i < 105; ++i) for (int j = 0; j < 10005; ++j) midL[i][j] = INF; memset(vis, false, sizeof(vis)); ans = INF; totalcost = 0; totalLen = 0; vis[1] = true; for (int i = 0; i < R; ++i) { cin >> s >> t.end >> t.length >> t.cost; if (s != t.end) { city[s].push_back(t); } } dfs(1); if (ans != INF) cout << ans << endl; else cout << -1 << endl; } return 0; }