标签: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 }
标签:div def i++ 信息 blog pop 割点 for 举例
原文地址:http://www.cnblogs.com/yyc-jack-0920/p/7615878.html