题目描述
在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3。其对应关系如下:距离s票价 0<S<=L1,C1;L1<S<=L2,C2;L2<S<=L3,C3。输入保证0<L1<L2<L3<109,0<C1<C2<C3<109。 每两个站之间的距离不超过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
分析
这是一道典型的动态规划的题目,这道题比较复杂的是有三种距离和三种票价,因此,在更新状态时要按照三种距离分别更新。理解了这一点,这道题就不会难以下手了。
这道题是求A到B的最小花费,首先要注意是A在前面还是B在前面,这也是一个坑。也就是说有可能是倒着往回走的,这种情况只需要将A和B的值互换就行了。这里使用了泛型swap函数,这个函数的作用就是交换两个变量的值。定义状态count[n]为A到n的最小花费,显然count[A] = 0,并且初始化count[n]为无穷大。状态转移方程有三个,分别对应三种距离。
当0<S<=L1时,count[n] = min(count[n],count[m] + C1),m为到n的距离小于L1的站。
当L1<S<=L2时,count[n] = min(count[n],count[m] + C2),m为到n的距离小于L2且大于L1的站。
当L2<S<=L3时,count[n] = min(count[n],count[m] + C3),m为到n的距离小于L3且大于L2的站。
另外还需要注意,这道题给出的距离均是到起点的距离,在实现时需要进行转换。
AC代码如下:
#include<iostream>
#include<algorithm>
#define MAX 1000000000//定义无穷大
using namespace std;
int main(void)
{
long long int l1, l2, l3, c1, c2, c3;
while(cin >> l1 >> l2 >> l3 >> c1 >> c2 >> c3)
{
int a, b, n;
cin >> a >> b >> n;
int* data = new int[n+1];//距离
long long int* count = new long long int[n+1];//花费
//初始化
data[0] = data[1] = 0;
count[0] = count[1] = 0;
for(int i = 2; i <= n; ++i)
{
cin >> data[i];
count[i] = MAX;
}
if(a > b)
{
swap(a, b);//注意a,b的大小,使用泛型swap函数交换值
}
count[a] = 0;//初始化A
for(int i = a; i < b; ++i)
{
int dis = 0;//两站之间的距离
for(int j = a + 1; j <= b; ++j)
{
dis = data[j] - data[i];//注意距离转换
//分别更新状态
if(dis <= l1)
{
count[j] = min(count[i]+c1, count[j]);
}
else if(dis <= l2)
{
count[j] = min(count[i]+c2, count[j]);
}
else if(dis <= l3)
{
count[j] = min(count[i]+c3, count[j]);
}
else//距离太远,没有相应的票
{
break;
}
}
}
cout << count[b];
delete [] data;
delete [] count;
}
return 0;
}