BZOJ 1003 [ZJOI2006]物流运输trans ★(Dijkstra + DP)

题目链接

http://www.lydsy.com/JudgeOnline/problem.php?id=1003

思路

先Dijkstra暴力求出i..j天内不变换路线的最少花费,然后dp[i] = min(cost[1..i], dp[j]+cost[j+1][i]+K). 总结: 1. BZOJ 题目质量果然高啊……做一道一次升华…… 2.自己太弱……

代码

  [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) using namespace std; struct edge{ int v, w; edge(int _v, int _w){ v = _v, w = _w; } }; typedef vector <edge> VI; priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > PQ; const int maxn = 25; VI adj[maxn]; int n, m, K, e, d; int cost[105][105], dist[maxn], flag[25][105], dp[105]; bool vis[maxn]; void dij(int l, int r){ while(!PQ.empty()) PQ.pop(); MEM(vis, 0); for (int i = 2; i <= m; i ++) dist[i] = 0x3fffffff; for (int i = 1; i <= m; i ++) for (int j = l; j <= r; j ++) if (flag[i][j]){ vis[i] = 1; break; } dist[1] = 0; PQ.push(make_pair(0, 1)); while(!PQ.empty()){ int u = PQ.top().second; PQ.pop(); for (int i = 0; i < (int)adj[u].size(); i ++){ int v = adj[u][i].v; if (!vis[v] && dist[v] > dist[u] + adj[u][i].w){ dist[v] = dist[u] + adj[u][i].w; PQ.push(make_pair(dist[v], v)); } } } if (dist[m] != 0x3fffffff) cost[l][r] = (r - l + 1) * dist[m]; else cost[l][r] = 0x3fffffff; //printf("l = %d r = %d cost = %d\n", l, r, cost[l][r]); } int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); scanf("%d %d %d %d", &n, &m, &K, &e); for (int i = 0; i <= m; i ++) adj[i].clear(); for (int i = 0; i < e; i ++){ int u, v, w; scanf("%d %d %d", &u, &v, &w); adj[u].push_back(edge(v, w)); adj[v].push_back(edge(u, w)); } scanf("%d", &d); MEM(flag, 0); for (int i = 0; i < d; i ++){ int p, l, r; scanf("%d %d %d", &p, &l, &r); for(int j = l; j <= r; j ++) flag[p][j] = 1; } for (int i = 1; i <= n; i ++){ for (int j = i; j <= n; j ++){ dij(i, j); } } for (int i = 1; i <= n; i ++) dp[i] = 0x3fffffff; dp[0] = 0; for (int i = 1; i <= n; i ++){ dp[i] = cost[1][i]; for (int j = 0; j < i; j ++){ if (cost[j+1][i] == 0x3fffffff) continue; dp[i] = min(dp[i], dp[j] + cost[j+1][i] + K); } } printf("%d\n", dp[n]); return 0; } [/cpp]

你可能感兴趣的:(dijkstra)