BZOJ 1003: [ZJOI2006]物流运输trans SPFA+DP
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
题解:
dp就好,令dp[i]表示第i天的答案,那么dp[i]=min{Cost(1,i),Cost(j+1,i)+dp[j]+K},其中Cost(i,j)表示从i到j都用同一种方案。这种dp和划分问题很类似。
代码:
#include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<cstdio> #include<climits> #define INF 0x3f3f3f3f #define MAX_M 220 #define MAX_N 1110 using namespace std; int N,M,K,E; int dp[MAX_N]; int d[MAX_M]; queue<int> que; bool inQue[MAX_M]; struct edge { public: int to, cost; edge(int t, int c) : to(t), cost(c) { } edge() { } }; vector<edge> G[MAX_M]; bool used[MAX_M]; vector<int> days[MAX_N]; int spfa() { while (que.size())que.pop(); memset(inQue, 0, sizeof(inQue)); fill(d, d + M + 1, INF); que.push(1); inQue[1] = 1; d[1] = 0; while (que.size()) { int u = que.front(); que.pop(); inQue[u]=0; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to, c = G[u][i].cost; if (d[v] > d[u] + c && (!used[v])) { d[v] = d[u] + c; if (!inQue[v]) { inQue[v] = 1; que.push(v); } } } } return d[M]; } int COST(int i,int j) { memset(used, 0, sizeof(used)); for (int k = i; k <= j; k++) for (int t = 0; t < days[k].size(); t++) used[days[k][t]] = 1; int tmp=spfa(); if(tmp==INF)return INF; return (j - i + 1) * tmp; } int main() { //freopen("1003.in", "r", stdin); //freopen("1003.out", "w", stdout); scanf("%d%d%d%d", &N, &M, &K, &E); for (int i = 0; i < E; i++) { int u, v, c; scanf("%d%d%d", &u, &v, &c); G[u].push_back(edge(v, c)); G[v].push_back(edge(u, c)); } int D; scanf("%d",&D); while (D--) { int P, a, b; scanf("%d%d%d", &P, &a, &b); for (int i = a; i <= b; i++)days[i].push_back(P); } for (int i = 1; i <= N; i++) { dp[i] = COST(1,i); for (int j = 1; j < i; j++) dp[i] = min(dp[i], COST(j + 1, i) + dp[j] + K); } printf("%d\n", dp[N]); return 0; }