题目描述
一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位)、每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站ii离出发点的距离Di、每升汽油价格Pi(i=1,2,…,N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入格式
第一行,D1,C,D2,P,N。
接下来有N行。
第i+1行,两个数字,油站i离出发点的距离Di和每升汽油价格Pi。
输出格式
所需最小费用,计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“No Solution”。
输入输出样例
输入 #1
275.6 11.9 27.4 2.8 2 102.0 2.9 220.0 2.2
输出 #1
26.95
说明/提示
N≤6,其余数字≤500
是一个贪心qwq,,策略大概是这个亚子:
先把给出的所有站按从远到近排序,然后开始模拟
对于当前的点,有这样几种情况:
1)到这个点时,剩的油可以到达终点,直接输出并结束
2)到这个点时,剩的油不可以到达终点,但是可以到达在它后边的比它花费小的站,那就到那个站
3)到这个点时,剩的油不可以到达终点,但是可以也不可以到达在它后边的比它花费小的站,那就看看加了油能不能到那个站,能的话就加油加到正好到那里
3)到这个点时,加满油也不可以到达在它后边的比它花费小的站,那就加油加满,走到在它后面的能走到的花费最小的站,也有可能加完油直接到终点
4)如果它根本就没有在它后边比它小的点,那么处理的方法就和3)一样
关于No Solution的情况
无非就是在一个点加满油也到不了下一个点(或终点),或者在最后一个站加满油也到不了终点
这个模拟过程好像可以循环做,,,但是我觉得dfs更好写一点点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
double mo,dis;
}sta[20];
int stam[20];
double d1,c,d2,p;
int n;
double anss;
bool cmp(node a,node b)
{
return a.dis<b.dis;
}
void dfs(int cur,double oil,double pri)
{
if(cur==n+1)//到了最后一个加油站
{
if(oil>=(d1-sta[cur].dis)/d2)cout<<pri,exit(0);//油是够的
if(oil<(d1-sta[cur].dis)/d2)//油不够
{
printf("%.2lf",pri+((d1-sta[cur].dis)/d2-oil)*sta[cur].mo);//加够
exit(0);
}
}
if(oil>=(sta[stam[cur]].dis-sta[cur].dis)/d2&&stam[cur])
{
dfs(stam[cur],oil-(sta[stam[cur]].dis-sta[cur].dis)/d2,pri);
}//油还能到下一个比它小的站 (首先它得有下一个比它花费小的站)
else //并不能到
{
if(stam[cur])//它有下一个比它花费小的站,那么按照贪心它下一步要去那里啦
{
if(c>=(sta[stam[cur]].dis-sta[cur].dis)/d2)// 加油之后可以下一个把他花费小的站
{
dfs(stam[cur],0,pri+(((sta[stam[cur]].dis-sta[cur].dis)/d2)-oil)*sta[cur].mo);
}
else
{
double minn=9999;int too;
double only=c*d2;//最多走的距离
if(only>=(d1-sta[cur].dis))
{
printf("%.2lf",pri+(d1-sta[cur].dis)/d2*sta[cur].mo);
exit(0);
}//在这里加了油可以直接到终点
for(int i=cur+1;i<=n+1;i++)//到不了终点qwq
if(sta[i].dis-sta[cur].dis<=only&&sta[i].mo<=minn)
{
minn=sta[i].mo;too=i;
}
pri+=(c-oil)*sta[cur].mo;//加满油,走到能到的花费最小的站
dfs(too,c-(sta[too].dis-sta[cur].dis)/d2,pri);
}
}
else//如果没有比它花费小的站了
{
double minn=9999;int too;
double only=c*d2;
if(only>=(d1-sta[cur].dis))//如果能到终点就到终点
{
printf("%.2lf",pri+(d1-sta[cur].dis)/d2*sta[cur].mo);
exit(0);
}
for(int i=cur+1;i<=n+1;i++)//不能到终点就加满油,走到能到的花费最小的站
if(sta[i].dis-sta[cur].dis<=only&&sta[i].mo<=minn)
{
minn=sta[i].mo;too=i;
}
pri+=(c-oil)*sta[cur].mo;
dfs(too,c-(sta[too].dis-sta[cur].dis)/d2,pri);
}
}
}
int main()
{
cin>>d1>>c>>d2>>p>>n;
sta[1].mo=p,sta[1].dis=0;
for(int i=2;i<=n+1;i++)
{
cin>>sta[i].dis>>sta[i].mo;
}
sort(sta+2,sta+(n+2),cmp);
for(int i=1;i<=n;i++)
if((min(sta[i+1].dis,d1)-sta[i].dis)>c*d2)
{cout<<"No Solution";exit(0);}
if(sta[n+1].dis+(c*d2)<d1)
{cout<<"No Solution";exit(0);}
for(int i=1;i<=n+1;i++)
for(int j=i+1;j<=n+1;j++)
if(sta[j].mo<=sta[i].mo)
{
stam[i]=j;break;
}
dfs(1,0,0);
}