【是题解】luoguP1016 旅行家的运算(贪心 模拟)

题目描述

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离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);
}

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值