18718 航行
Description
银河帝国正走向覆亡。为保留文明的种子,你需要驾驶飞船将一批“颛家”从帝国首都护送至银河边缘的基地。
现在已知航线是一条直线,帝国首都为起点(坐标0),基地为终点(坐标L),在这条航线上有N个空间站可以补充飞船的能源。
第i个空间站的坐标为ai,飞船停靠在第i个空间站必须花费bi个银河币,同时让你的飞船能量恢复为最大值M。
出发前飞船的能量是满额的M,每一点能量都可以让飞船航行一个坐标单位。
现在你已经通过募捐(榨篇)获得了S个银河币,请计算下飞船能否到达基地。
输入格式
第一行输入四个个数字N,L,M,S;(1<=N<=200) (1<=L<=20000) (1<=M<=20000) (0<=S<=20000)
接下来N行,每行输入两个数字,ai,bi (0<=ai<=L) (0<=bi<=20000)
输出格式
仅一行,如果能到达基地,输出Yes,否则输出No
输入样例
1 10000 5000 20000
5000 20000
输出样例
Yes
提示
样例说明,飞船可以花费5000能量到达一号空间站,花光20000银河币补满能量后,再行驶5000到达基地。
算法设计要考虑边缘数据。例如本题目,可能存在无需补给就直接行驶到基地的情况,也能存在bi>s的情况。
正确代码:参考:18718 航行(深搜/暴力)
深度搜索,每走一步就判断能否走下一步
PS:距离和坐标的关系!
#include <iostream>
using namespace std;
//定义结构体,包含空间站坐标和银河币花销
struct node
{
int xy;//空间站坐标
int cost;//花销
}spa[250];//重命名为Spa[]
int N,L,M,S;
bool flag = false;//能否到达基地的标记
void dfs(int money,int energy,int pos,int num)//每一次的消费,补充的能量(常为M),当前站点坐标,当前站点(Spa索引)
{
//出口(条件:不管有没有用完钱,只判断能否到终点)
if(pos + energy >= L){ //初始能量+补充的能量能支撑到达基地
flag = true;
return;
}
//没到基地,进行深搜
//到下一个空间站补给
for(int i = num + 1 ;i <= N;i++){ //从下一个空间站开始搜索
//判断能否走下一步
//钱够在第i个站点消费 && 能量足够到达第i空间站(即能量 > 两空间站之间距离)
//两空间站之间距离 = 第i个空间站坐标-上一个空间站坐标,记住是坐标!!求距离要坐标相减
if(money >= spa[i].cost && energy >= spa[i].xy - pos){
//花钱了,补充能量,然后继续搜索下一个空间站
dfs(money - spa[i].cost, energy, spa[i].xy,num + 1);//到达下一个空间站,继续搜索
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> N >> L >> M >> S;
//输入结构体
for(int i = 1;i <= N;i++){
//输入第i个站点的坐标和花销
cin >> spa[i].xy >> spa[i].cost;
}
if(M >= L){ //初始能量足够直接到达终点
flag = 1;
}
//进行深搜,从S,0,0开始(原点)
dfs(S,M,0,0);
if(flag){
cout << "Yes";
}
else{
cout << "No";
}
return 0;
}
尝试方法1(错误的!!!)
队列,所有空间站入队,在判断是否停靠
(无法AC,但是实在找不到哪里错了(太混乱),放弃这个思路了)
#include <iostream>
#include <queue>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int N,L,M,S;
cin >> N >> L >> M >> S;
int a,b;
//构建队列
queue<int> A;//坐标(路程)
queue<int> B;//银河币
//坐标和需花费的银河币入队
for(int i = 0;i < N;i++){
cin >> a >> b;
A.push(a);
B.push(b);
}
//L入队
A.push(L);
/*for(int i = 0;i < N + 1;i++){
cout << A.front() << " ";
A.pop();
}*/
//能量M足够行驶到基地
if(M >= L){
cout << "Yes" << endl;
return 0;
}
//遍历队
int t,x,d = A.front(),res = M;
while(A.front() < L){//当A队列只剩L时即到达基地
x = d;//上一个空间站到本次空间站的距离(上段路程)
res = res - d;//到达当前空间站时剩余能量
t = A.front();
A.pop();
d = A.front() - t;//当前空间站到下一个空间站的距离
if(res < 0){ //上一站和本站的距离大于满额的能量,无法到达
cout << "No" << endl;
return 0;
}
else if(res - d <= 0){ //剩余能量不足以到达下一个空间站,因此需要在当前空间站停靠
if(S <= 0 && A.front() != L){ //没钱了且下一站不是基地
cout << "No" << endl;
return 0;
}
S -= B.front();
res = M;//充满能量
B.pop();
}
else{ //剩余能量足够支撑到达下一个空间站,本次不停靠
B.pop();
}
}
//遍历结束,飞船到基地
cout << "Yes" << endl;
return 0;
}