bzoj 1003 物流运输

题目大意:

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

给出一些信息,表示第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

 

posted @ 2017-09-30 18:31  jack_yyc  阅读(164)  评论(0编辑  收藏  举报