题目描述:
在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下:
距离s 票价
0<S<=L1 C1
L1<S<=L2 C2
L2<S<=L3 C3
输入保证0<L1<L2<L3<10^9,0<C1<C2<C3<10^9。
每两个站之间的距离不超过L3。
当乘客要移动的两个站的距离大于L3的时候,可以选择从中间一个站下车,然后买票再上车,所以乘客整个过程中至少会买两张票。
现在给你一个 L1,L2,L3,C1,C2,C3。然后是A B的值,其分别为乘客旅程的起始站和终点站。
然后输入N,N为该线路上的总的火车站数目,然后输入N-1个整数,分别代表从该线路上的第一个站,到第2个站,第3个站,……,第N个站的距离。
根据输入,输出乘客从A到B站的最小花费。
输入:
以如下格式输入数据:
L1 L2 L3 C1 C2 C3
A B
N
a[2]
a[3]
……
a[N]
输出:
可能有多组测试数据,对于每一组数据,
根据输入,输出乘客从A到B站的最小花费。
样例输入:
1 2 3 1 2 3
1 2
2
2
样例输出:
2
代码:
#include<stdio.h>
#define MAXN 2211686018427387904
#define MAXS 30000
long long l1,l2,l3,c1,c2,c3,rout[MAXS];
long long spe(int start,int end)//输入起始点与终点的站号,输出这俩站之间的花费。
{
int temp=rout[end]-rout[start];
if(temp<=l1)return c1;
if(temp<=l2)return c2;
if(temp<=l3)return c3;
return MAXN;
}
int main()
{
long long temp,i,j,a,b,n,spend[MAXS];
while(~scanf("%lld %lld %lld %lld %lld %lld",&l1,&l2,&l3,&c1,&c2,&c3))
{
for(i=temp=0;i<MAXS;i++)rout[i]=spend[i]=MAXN;
scanf("%lld %lld",&a,&b);
scanf("%lld",&n);
rout[1]=0;
for(i=2;i<=n;i++)scanf("%lld",&rout[i]);
for(i=a,spend[a]=0;i<b;i++)
{
for(j=i+1;rout[j]-rout[i]<=l3&&j<MAXS;j++)//保证下面spe函数的输入俩站间距离是小于等于l3的。
{
temp=spe(i,j);
if(spend[j]>spend[i]+temp)spend[j]=spend[i]+temp;
}
}
printf("%lld\n",spend[b]);
}
return 0;
}
翻了说有一篇思路很好,虽然是java也复制一下
代码
package Test1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Test15_1086 {
/**
* by qr jobdu 1086 2014-8-12
* @throws IOException
*
* Accepted 70MS
*/
static long L1,L2,L3,C1,C2,C3;
public static void main(String[] args) throws IOException {
StreamTokenizer st=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
while((st.nextToken())!=StreamTokenizer.TT_EOF){
L1=(long)st.nval; //long型
st.nextToken();
L2=(long)st.nval;
st.nextToken();
L3=(long)st.nval;
st.nextToken();
C1=(long)st.nval;
st.nextToken();
C2=(long)st.nval;
st.nextToken();
C3=(long)st.nval;
st.nextToken();
int A=(int)st.nval;
st.nextToken();
int B=(int)st.nval;
st.nextToken();
int N=(int)st.nval;
long a[]=new long[N+1]; //第一个站到第N个站的距离
a[1]=0;
for(int i=2;i<=N;i++){
st.nextToken();
a[i]=(int)st.nval;
}
//get the min cost
long disAB=a[B]-a[A];
if(B==A) //!!
System.out.println("0");
else if(disAB<=L1)
System.out.println(C1);
else if(disAB<=L2)
System.out.println(C2);
else if(disAB<=L3)
System.out.println(C3);
else{ //>L3 分段 动态规划思想
long mincost[]=new long[B-A+1]; //0号元素是A ,1号元素是A+1。。。。。B-A号元素是B ,i号元素代表A站到第i站的最小花费
// mincost[0]=0; // do not necessary 初始就是0
for(int i=A+1;i<=B;i++){ //每for循环一次确定到一个站的最小花费
int count=0;
while( count <= i-(A+1)&& a[i]-a[i-count-1] <= L3 ){ //计算本站前面不超过L3的站有几个 第i站到A站 第i站和第A站之间最多有(i-(A+1))个站
count++;
}
long min=Long.MAX_VALUE;
for(int j=0;j<count;j++){ //依次算出 到本站的最小花费。 实用动态规划的思想。 min为到第i站的最小花费
min=Math.min(min, mincost[i-(A+1)-j]+getCost(a[i]-a[i-j-1]));
}
mincost[i-A]=min;
}
System.out.println(mincost[B-A]);
}
}
}
static long getCost(long dis){
if(dis==0)
return 0;
else if(dis<=L1)
return C1;
else if(dis<=L2)
return C2;
else
return C3;
}
}
思路
http://www.cnblogs.com/love533/archive/2012/04/01/2429200.html
动态规划思想完全参照该篇博文
这篇文章的做法非常巧妙,AC后时间和空间都是目前提交中最优的。
mincost数组存储A站到B及A,B站之间的站的最小费用,从离A近的站开始求。
每次求最小费用有两个步骤
1.找到本站之前距离不超过L3的站的个数count
2.循环count次,将费用分成两段,A站到中间站+中间站到所求站。找到最小的费用。
A站到中间站存储在mincost中,中间站到所求站距离不超过L3,费用已知
开始有个疑问是,A站到X站中有X1和X2站,将费用分成三段,A站到X1站+X1站到X2站+X2站到X站,
三段费用才是最小费用,会不会出现这种情况?肯定不会,因为在求A到X站的最小费用时,
肯定已经求出A站到X2站的最小费用了,不可能存在一个X1站使整体的费用更小。
另外,不要忘记将费用分段,只有超出L3才用动态规划。
另外Java中初始化数组会默认元素为0,则不必再为mincost[0]赋值为0