题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
解:一个很神奇的dp,预处理所有连续时间段内的最小花费(w[i][j]表示第i天到第j天的最小花费),然后以f[x]表示到第x天为止的最小花费,用f[j]=min(f[j], f[i]+w[i+1][j]+K)更新即可
1 /* 2 * Problem: 3 * Author: SHJWUDP 4 * Created Time: 2015/6/9 星期二 11:06:58 5 * File Name: 233.cpp 6 * State: 7 * Memo: 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 #include <queue> 14 15 using namespace std; 16 17 const int INF=0x7f7f7f7f; 18 19 const int MaxA=100+7; 20 const int MaxB=20+7; 21 22 struct Edge { 23 int v, nt; 24 int w; 25 Edge(){} 26 Edge(int v, int nt, int w):v(v), nt(nt), w(w){} 27 } edges[MaxB*MaxB*2]; 28 29 int head[MaxB], edgeNum; 30 31 struct Data { 32 int P, a, b; 33 } op[MaxA]; 34 35 int n, m, K, e, d; 36 int w[MaxA][MaxA]; 37 int f[MaxA]; 38 bool used[MaxA]; 39 void init() { 40 memset(head, -1, sizeof(head)); 41 edgeNum=0; 42 } 43 void addEdge(int u, int v, int w) { 44 edges[edgeNum]=Edge(v, head[u], w); 45 head[u]=edgeNum++; 46 } 47 void build(int s, int t) { 48 memset(used, 0, sizeof(used)); 49 for(int i=0; i<d; i++) { 50 if(op[i].b<s || op[i].a>t) continue; 51 used[op[i].P]=1; 52 } 53 } 54 namespace Dijkstra { 55 struct HeapNode { 56 int d, u; 57 HeapNode(int d, int u):d(d), u(u) {} 58 bool operator<(const HeapNode& rhs) const { 59 return d>rhs.d; 60 } 61 }; 62 63 int d[MaxB]; 64 int done[MaxB]; 65 66 void go(int s) { 67 priority_queue<HeapNode> Q; 68 memset(d, 0x7f, sizeof(d)); 69 memset(done, 0, sizeof(done)); 70 71 Q.push(HeapNode(0, s)); d[s]=0; 72 while(!Q.empty()) { 73 HeapNode x=Q.top(); Q.pop(); 74 if(done[x.u]) continue; 75 done[x.u]=1; 76 for(int i=head[x.u]; ~i; i=edges[i].nt) { 77 Edge& e=edges[i]; 78 if(used[e.v]) continue; 79 if(d[x.u]+e.w<d[e.v]) { 80 d[e.v]=d[x.u]+e.w; 81 Q.push(HeapNode(d[e.v], e.v)); 82 } 83 } 84 } 85 } 86 } 87 int main() { 88 #ifndef ONLINE_JUDGE 89 freopen("in", "r", stdin); 90 // freopen("out", "w", stdout); 91 #endif 92 while(~scanf("%d%d%d%d", &n, &m, &K, &e)) { 93 init(); 94 for(int i=0; i<e; i++) { 95 int a, b, c; 96 scanf("%d%d%d", &a, &b, &c); 97 addEdge(a, b, c); 98 addEdge(b, a, c); 99 } 100 scanf("%d", &d); 101 for(int i=0; i<d; i++) { 102 scanf("%d%d%d", &op[i].P, &op[i].a, &op[i].b); 103 } 104 for(int i=1; i<=n; i++) { 105 for(int j=i; j<=n; j++) { 106 build(i, j); 107 Dijkstra::go(1); 108 w[i][j]=Dijkstra::d[m]; 109 if(w[i][j]<INF) w[i][j]*=j-i+1; 110 } 111 } 112 for(int j=1; j<=n; j++) { 113 f[j]=w[1][j]; 114 for(int i=1; i<j; i++) { 115 if(w[i+1][j]>=INF || f[i]>=INF) continue; 116 f[j]=min(f[j], f[i]+w[i+1][j]+K); 117 } 118 } 119 printf("%d\n", f[n]); 120 } 121 return 0; 122 }