码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1003 物流运输

时间:2017-09-30 20:57:32      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:div   def   i++   信息   blog   pop   割点   for   举例   

题目大意:

一个无向图起点和终点,和一个天数

给出一些信息,表示第c个码头在【a,b】天内不可用。保证任意一天有一条起点到终点的路径

每天的花费为选择的路径长度

而每次更改路径都会增加额外的花费为一个给定常数

求最后这些天的总花费最小值

思路:

首先可以想到对于每天当前情况下的最短路,我写了好写的spfa

当然可以想到dp

然后发现计算每天的最短路不太好写因为必须判断两天之间最短路不同况且这样dp很难写

就可以开一个数组记录一下【i,j】天内共同的最短路

然后对于每个dp[i] 枚举分割点 dp[i]=min(dp[i],dp[j]+c[j+1][i]*(i-j)+p) 其中c为上述数组,p为改变路径费用

为什么对于每个点都可以加上p而不用判断,因为这样不会影响结果,可以举例说明

然后做完了

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2147483611
10 #define ll long long 
11 #define MAXN 25
12 using namespace std;
13 int read()
14 {
15     int x=0,f=1;
16     char ch=getchar();
17     while(ch<0||ch>9) {if(ch==-) f=-1;ch=getchar();}
18     while(ch>=0&&ch<=9) {x=x*10+ch-0;ch=getchar();}
19     return x*f;
20 }
21 int n,p,m,days;
22 int first[MAXN],next[MAXN*MAXN*3];
23 struct data
24 {
25     int dis,to;
26 }edge[MAXN*MAXN*MAXN];
27 int dis[MAXN];
28 bool vis[MAXN];
29 long long dp[MAXN*5],c[MAXN*5][MAXN*5];
30 bool mark[MAXN][MAXN*5];
31 bool ok[MAXN];
32 int spfa(int l,int r)
33 {
34     queue <int> q;
35     memset(vis,false,sizeof(vis));
36     memset(dis,127/3,sizeof(dis));
37     memset(ok,false,sizeof(ok));
38     q.push(1);vis[1]=true;dis[1]=0;
39     for(int i=l;i<=r;i++)
40         for(int j=1;j<=m;j++) if(mark[j][i]) ok[j]=1;
41     while(!q.empty())
42     {
43         int k=q.front();
44         vis[k]=0;
45         q.pop();
46         for(int i=first[k];i;i=next[i])
47         {
48             int a=edge[i].to;
49             if(dis[a]>dis[k]+edge[i].dis&&!ok[a])
50             {
51                 dis[a]=dis[k]+edge[i].dis;
52                 if(!vis[a]) {vis[a]=true;q.push(a);}
53             }
54         }
55     }
56     return dis[n];
57 }
58 int main()
59 {
60     days=read();n=read();
61     p=read();m=read();
62     int cnt=1;
63     for(int i=1;i<=m;i++)
64     {
65         int a=read(),b=read(),c=read();
66         next[cnt]=first[a],first[a]=cnt,edge[cnt].dis=c,edge[cnt++].to=b;
67         next[cnt]=first[b],first[b]=cnt,edge[cnt].dis=c,edge[cnt++].to=a;
68     }
69     int t=read();
70     while(t--)
71     {
72         int a=read(),l=read(),r=read();
73         for(int i=l;i<=r;i++)  mark[a][i]=true;
74     }
75     for(int i=1;i<=days;i++)
76         for(int j=i;j<=days;j++)
77             c[i][j]=spfa(i,j);
78     for(int i=1;i<=days;i++)
79     {
80         dp[i]=(ll)(c[1][i]*i);
81         for(int j=0;j<i;j++)
82         {
83             dp[i]=min(dp[i],dp[j]+p+c[j+1][i]*(i-j));
84         }
85     }
86     printf("%lld",dp[days]);
87 }
View Code

 

bzoj 1003 物流运输

标签:div   def   i++   信息   blog   pop   割点   for   举例   

原文地址:http://www.cnblogs.com/yyc-jack-0920/p/7615878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!