对于每一个时间区间(共N^2个)我们都做一次最短路,然后DP。
#include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <fstream> #include <iostream> #include <queue> #define rep(i, l, r) for(int i=l; i<=r; i++) #define N 23 #define MAX 1<<30 #define clr(x, c) memset(x, c, sizeof(x)) using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar(); } while (ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct edge{int y, n, z;} e[N*N*2]; int fir[N], en; struct data { int x, d; data(int a, int b) : x(a), d(b) {} bool operator < (const data &k) const { return d>k.d; } }; int n, m, v, p, d[N], k[123][123]; bool c[N][123]; inline void Add(int x, int y, int z) { en++, e[en].y=y, e[en].z=z, e[en].n=fir[x], fir[x]=en; en++, e[en].y=x, e[en].z=z, e[en].n=fir[y], fir[y]=en; } int main() { n=read(); m=read(); v=read(); clr(c, 1); p=read(); rep(i, 1, p) { int x=read(), y=read(), z=read(); Add(x, y, z); } p=read(); rep(o, 1, p) { int z=read(), x=read(), y=read(); rep(i, x, y) c[z][i]=false; } rep(s, 1, n) rep(t, s, n) { rep(i, 1, m) d[i]=-1; priority_queue<data> q; q.push(data(1, 0)); while (d[m]<0 && !q.empty()) { data a=q.top(); q.pop(); int x=a.x, o=fir[x], y=e[o].y; bool end=false; rep(i, s, t) if (!c[x][i]) end=true; if (end) continue; if (d[x]<0) d[x]=a.d; else continue; while (o) q.push(data(y, d[x]+e[o].z)), o=e[o].n, y=e[o].y; } if (d[m]<0) k[s][t]=MAX; else k[s][t]=d[m]*(t-s+1); } rep(i, 0, n-1) rep(j, 1, n-i) rep(o, j, j+i-1) k[j][j+i]=min(k[j][j+i], k[j][o]+k[o+1][j+i]+v); printf("%d ", k[1][n]); return 0; }