从Ekaterinburg到Sverdlovsk的火车线路上有若干个站点。这条线路可以近似的表示为一条线段,火车站就是线段上的点。线路始于Ekaterinburg,终于Sverdlovsk。Ekaterinburg被标号为1,Sverdlovsk被标号为n。(n为整条线路上的站点数)
线路上的任意两个站点间的直达票价是由它们间的距离决定的,票价根据以下规则制定:
X为两站的距离 价格
0<X<=L1 C1
L1<X<=L2 C2
L2<X<=L3 C3
如果两站的间距超过L3,则无直达车票。所以有时可能有必要买多张票,通过转车的方式,从一个站到达另一个站。
例如,在上面的图中,有7个站点。2号站点到6号站点的距离超过L3,不能买直达票。存在若干种中转的方法,其中的一种是买两张票:先花费C2从2号站到达3号站,然后花费C3从3号站到6号站,一种花费C2+C3。
你的任务是,找出一种最经济的中转方案。
输入
从文本文件railway.in中读入数据。
第一行6个整数L1, L2, L3, C1, C2, C3(1<=L1<l2<l3<=10^9, 1<="C1<C2<C3<=10^9),中间用空格分隔。"第二行一个整数n(2<=n<=100),表示线路上的车站数。
第三行两个整数s和t,分别是起点和终点的编号。注意:s不一定小于t。
以下的n-1行,按据Ekaterinburg远近,每行描述了一个车站的位置。它包含一个整数,表示该车站距Ekaterinburg的距离。
任意两个车站的距离不超过10^9,任意两个相邻的车站的距离不超过L3。
输出
一个整数,表示从给定的一个站到给定的另一个站的最小花费。
【样例输入】
3 6 8 20 30 40 7 2 6 3 7 8 13 15 23
【样例输出】
70水题,按照题目要求建边即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int l1,l2,l3,c1,c2,c3,s,t;
int h[105],d[105],cnt;
int a[105],n;
queue<int> q;
bool vis[105];
struct que
{
int to,next,v;
}w[20005];
void add(int x,int y,int z)
{
cnt++;
w[cnt].to=y;
w[cnt].v=z;
w[cnt].next=h[x];
h[x]=cnt;
}
void spfa()
{
memset(d,0x3f,sizeof(d));
q.push(s);
d[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=h[u];i;i=w[i].next)
{
int to=w[i].to;
if(d[u]+w[i].v<d[to])
{
d[to]=d[u]+w[i].v;
if(!vis[to])
{
q.push(to);
vis[to]=1;
}
}
}
}
}
int main()
{
scanf("%d%d%d%d%d%d",&l1,&l2,&l3,&c1,&c2,&c3);
scanf("%d",&n);
scanf("%d%d",&s,&t);
for(int i=2;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)//避免重边
{
if(i==j) continue;
if(a[j]-a[i]>l3) break;//简单优化,速度影响不大
if(a[j]-a[i]<=l1)
{
add(i,j,c1);
add(j,i,c1);
}
else if(a[j]-a[i]>l1&&a[j]-a[i]<=l2)
{
add(i,j,c2);
add(j,i,c2);
}
else if(a[j]-a[i]>l2&&a[j]-a[i]<=l3)
{
add(i,j,c3);
add(j,i,c3);
}
}
spfa();
printf("%d",d[t]);
}