[ZJOI2006]物流运输 (最短路+dp)

来源:互联网 发布:win7电脑摄像头软件 编辑:程序博客网 时间:2024/06/05 05:47

如果本题没有换线路要k的花费这个条件,很明显就是直接枚举天数,每次都跑一个最短路即可。但是现在有这个条件,我们就要加上dp的思想,来分段决策。

解法:

1.枚举起始天和终止天,然后排除这个范围内无法一直有效的点,跑一遍最短路,用cost[i][j]记录此时到达港口m的最小花费。

2.进行一次dp,dp[i]代表的是第i天开始到第n天的最小花费,边界为dp[n + 1] = -k。然后从第n天当成起始天,开始向后枚举,枚举终止天。转移方程为:dp[i] = min(dp[i], dp[j + 1] + cost[i][j] * (j - i + 1) + k).

代码如下:

#include<iostream>#include<cstdio>#include<vector>#include<queue>#include<utility>#include<stack>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<set>#include<map>using namespace std;typedef pair<int, int> pii;const int maxn = 25;const int INF = 1e7;int n, m, k, e;int dis[maxn], dp[105];int vst[maxn][105], cost[105][105];bool flag[25];vector <pii> edge[maxn];void dijkstra() {fill(dis, dis + maxn, INF);priority_queue <pii, vector<pii>, greater<pii> > q;dis[1] = 0;q.push(pii(dis[1], 1));while(!q.empty()) {pii tmp = q.top();q.pop();int u = tmp.second;if(dis[u] < tmp.first)continue;if(u == m)break;for(int i = 0; i < edge[u].size(); i++) {int d = edge[u][i].first + dis[u];int v = edge[u][i].second;if(flag[v])continue;if(dis[v] > d) {dis[v] = d;q.push(pii(dis[v], v));}}}}void build(int front, int back) {memset(flag, 0, sizeof(flag));for(int i = 1; i <= m; i++) {for(int t = front; t <= back; t++) {if(vst[i][t]) {flag[i] = 1;break;}}}}int main() {#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);#endifscanf("%d%d%d%d", &n, &m, &k, &e);while(e--) {int u, v, val;scanf("%d%d%d", &u, &v, &val);edge[u].push_back(pii(val, v));edge[v].push_back(pii(val, u));}int d;scanf("%d", &d);while(d--) {int a, b, p;scanf("%d%d%d", &p, &a, &b);for(int i = a; i <= b; i++) {vst[p][i]++;}}for(int i = 1; i <= n; i++) {for(int j = i; j <= n; j++) {build(i, j);dijkstra();cost[i][j] = cost[j][i] = dis[m];//cout << "i is " << i << " j is " << j << " ans is " << dis[m] << '\n';}}memset(dp, 0x3f, sizeof(dp));dp[n + 1] = -k;for(int i = n; i; i--) {for(int j = i; j <= n; j++) {dp[i] = min(dp[i], dp[j + 1] + cost[i][j] * (j - i + 1) + k);}}printf("%d\n", dp[1]);return 0;}


阅读全文
0 0
原创粉丝点击