bzoj1003 (dp+Dijkstra)
阿新 • • 發佈:2018-12-17
分析:核心是要計算出任意x天不改變路線所需的花費,即此處的dis[i][j],再用動態規劃搞一下就可以了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1000000007; const int maxn = 105; const int INF = 1e9; typedef struct edge { int from, to, dist; edge(int u, int v, int d) :from(u), to(v), dist(d) {} }edge; typedef struct heapnode { int d, u; bool operator <(const heapnode& rhs) const {return d > rhs.d;} }heapnode; int days,m,K,e; int avl[maxn][maxn]; int dis[maxn][maxn]; int can[maxn]; int dp[maxn]; typedef struct Dijkstra { int n, m; vector<edge>edges; vector<int>G[maxn]; bool done[maxn]; int d[maxn]; int p[maxn]; void init(int n) { this->n = n; for(int i=0;i<n;i++) G[i].clear(); edges.clear(); } void add_edge(int from, int to, int dist) { edges.push_back(edge(from, to, dist)); m = edges.size(); G[from].push_back(m - 1); } void dijkstra(int s) { priority_queue<heapnode>Q; for(int i=0;i<n;i++) d[i] = INF; d[s] = 0; memset(done,0,sizeof(done)); Q.push(heapnode{ 0,s }); while (!Q.empty()) { heapnode x = Q.top(); Q.pop(); int u = x.u; if (done[u]) continue; done[u] = true; for(int i=0;i<G[u].size();i++) { edge &e = edges[G[u][i]]; if (d[e.to] > d[u] + e.dist&&!can[e.to]) { d[e.to] = d[u] + e.dist; p[e.to] = G[u][i]; Q.push(heapnode{ d[e.to],e.to }); } } } } }Dijkstra; Dijkstra D; Dijkstra *f=&D; void solve() { for(int i=0; i<maxn; i++) for(int j=0; j<maxn; j++) dis[i][j]=INF; for(int i=1; i<=days; i++) { for(int j=i; j<=days; j++) { memset(can,0,sizeof(can)); for(int k=0; k<m; k++) for(int g=i; g<=j; g++) can[k]|=avl[k][g]; f->dijkstra(0); dis[i][j]=f->d[m-1]; if(dis[i][j]<INF) dis[i][j]*=(j-i+1); } } } void DP() { for(int i=1;i<=days;i++) dp[i]=dis[1][i]; for(int i=2;i<=days;i++) for(int j=1;j<i;j++) dp[i]=min(dp[i],dp[j]+dis[j+1][i]+K); } int main() { int u, v, w; scanf("%d%d%d%d",&days,&m,&K,&e); f->init(m); for(int i=0;i<e;i++) { scanf("%d%d%d",&u,&v,&w); u--,v--; f->add_edge(u,v,w); f->add_edge(v,u,w); } memset(avl,0,sizeof(avl)); int num,st,ed; scanf("%d",&num); for(int i=0;i<num;i++) { scanf("%d%d%d",&u,&st,&ed); u--; for(int j=st;j<=ed;j++) avl[u][j]=1; } solve(); DP(); printf("%d\n",dp[days]); return 0; }