分析:这里最笨的方法是使用递归下的深度优先搜索(为啥感觉好像每个题目都可以深度搜索一样,蜜汁尴尬),对于每个加油站,有加油和不加油两个选择。然而在看到限制条件中1<=N<=10000后,我知道这种方法显然不可取了,即便可以在大于已知最小次数时进行剪枝,可是效率仍然是非常低的。
我们结合下实际情况:我们想象下,车子在还有油时,不断向前行驶,每遇到一个加油站i时,都把Bi量的油放在车上,注意这并不是给油缸加油,只是相当于放在后备箱了,然后在车子没有油时,从后备箱选择一个油量最大的进行加油,这样不断重复,在后备箱中已经没有油,但是还没到终点,那么就不能到终点了,也就是输出-1。比较类似贪心,每次选择一个对当前情况最有利的情况。
在进行选择后备箱的油时,当然可以使用循环不断比较后获得最大油量,可是没必要,我们可以使用C++的STL库中的一个数据结构---优先队列priority_queue,每次把油加入后备箱时,都会自动按int类型键值从大到小排序,然后每次从后备箱取油时,会自动返回最大油量.下面是源代码:
#include<iostream>
#include<queue>
using namespace std;
#define Max 10000
int n,l,p;
int A[Max],B[Max];
int solve()
{
//ans表示最后结果,即最小加油次数
//pos表示当前卡车位置
//tank表示油缸中油的数量
//que优先队列中存放之前能通过的各个加油站的最大加油量Bi
priority_queue<pair<int,int> > que;
int ans=0,pos=0,tank=p;
for(int i=0;i<n;i++)
{
int curDist=A[i]-pos; //curDist表示到达下一个临时终点(加油站)的距离
while(curDist>tank) //当前油不够到下一个终点
{
if(que.empty())
{
//cout<<"无法到达终点~"<<endl;
return -1;
}
pair<int,int> temp=que.top();
que.pop();
tank+=temp.first; //不断加油,直到能到达下一个终点
cout<<temp.second+1<<" ";
ans++;
}
tank-=curDist; //跑到下一个终点,消耗 curDist数量的油
pos=A[i]; //到达下一个加油站,取得该加油站的油,放在优先队列中,以便后面使用
que.push(make_pair(B[i],i));
}
cout<<endl;
return ans;
}
int main()
{
cin>>n>>l>>p;
for(int i=0;i<n;i++)
{
cin>>A[i]>>B[i];
}
cout<<"加油的站点的编号:";
cout<<solve();
return 0;
}
PS:开学之后,博客可能没办法像寒假一样频繁地更新,虽然最近每天看的内容挺多,但是很多是原来基础的一些数据结构的知识,开学后,我会有选择地写下比较有代表性或者有自己心得的博客。