[ZJOI2006 物流运输trans] 最短路径 DP SPFA
From:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
Solution:
记cost[i,j]表示i到j天不换路径的最小成本, dp[i]表示前i天的最小成本, 得dp[i] = min(dp[i], dp[j]+cost[j+1,i]+K),其中0<=j<i.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/************************************************************** Problem: 1003 User: leezy Language: C++ Result: Accepted Time:64 ms Memory:888 kb ****************************************************************/ #include #include #include #include #include #include #include #include using namespace std; #define N 25 #define M 105 #define INF 0x6fffffff #define MAX_LEVEL 32 #define NIL (-1) #define lowbit(i) ((i)&(-i)) bool inQ[N], valid[N][M]; int w[N][N], d[N], dp[M], S, T, cost[M][M]; void init(int n, int m){ S = 1, T = n; for (int i = 0; i <=n; ++i){ for (int j = 0; j <= n; ++j) w[i][j] = INF; for (int j = 0; j <= m; ++j) valid[i][j] = true; } } bool check(int v, int i, int j){ bool r = true; for (int k = i; k <= j; ++k) r &= valid[v][k]; return r; } int spfa(int I, int J){ std::queue Q; for (int i = S; i <= T; ++i) inQ[i] = false, d[i] = INF; d[S] = 0; inQ[S] = true; Q.push(S); while ( !Q.empty() ){ int u = Q.front(); Q.pop(); inQ[u] = false; for (int v = S; v <= T; ++v){ if ( w[u][v] == INF ) continue; if ( d[v] - d[u] > w[u][v]){ if ( check(v, I, J) ){ d[v] = d[u] + w[u][v]; if ( v != T && !inQ[v] ){ Q.push(v); inQ[v] = true; } } } } } return d[T]; } int run(int n, int m, int K){ for (int i = 1; i <= m; ++i) for (int j = i; j <= m; ++j){ cost[i][j] = spfa(i, j); if ( cost[i][j] != INF ) cost[i][j] *= (j-i+1); } dp[0] = -K; for (int i = 1; i <= m; ++i) dp[i] = INF; for (int i = 1; i <= m; ++i) for (int j = 0; j < i; ++j ) dp[i] = min(dp[i], dp[j] + cost[j+1][i] + K); return dp[m]; } int main() { //const char path[] = "D:\\Project\\AlgorithmExam\\test.txt"; //freopen(path, "r+", stdin); int n,m,K,e; while( scanf("%d%d%d%d", &n, &m, &K, &e) != EOF ){ init(m, n); for (int i = 0; i < e; ++i){ int a, b, x; scanf("%d%d%d", &a, &b, &x); w[a][b] = w[b][a] = x; } int nn = 0; scanf("%d", &nn); for (int i = 0; i < nn; ++i){ int a, b, x; scanf("%d%d%d", &x, &a, &b); for (int i = a; i <= b; ++i) valid[x][i] = false; } printf("%d\n", run(m, n, K)); } return 0; }