题目:
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
//这道题刚开始没想到广搜,其实就是把普遍广搜深搜模板题的四个或者八个方向变成了三个方向,本质都是每个都要搜一遍;
//queue用法:
queue<typename> name; //typename可以是任意基本基本数据类型或者容器;
queue为一个容器,符合先进先出原则,即可以用q.push往q里插入数据,删除数据的时候用q.pop()按照输入顺序删除;
一些queue常用函数:
1.push() 在队尾插入一个元素;
2.pop() 删除队列第一个元素;
3.size()返回队列中元素个数;
4.empty()判断队列是否为空,如果为空返回ture;
5.front() 返回队列中第一个元素;
6.back() 返回队列中最后一个元素;
//优先队列写法
priority_queue<long long,vector<long long>,greater<long long> >q;
可以将long long改成int或者其他类型;
greater为从小到大排序;
换成less为从大到小排序;
函数用法与queue一样只是多了排序;
//q.top() 返回队列第一个值
// q.swap 交换内容
// emplace 原地构造一个元素并插入队列
本题代码
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<string.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,k,vis[N];
struct node
{
int x;
int step;
};
void bfs()
{
queue<node>q;//相当于创建一个数组包含结构体中的变量
node star,now,next;//定义三个结构体
memset(vis,0,sizeof(vis));
star.x=n;//开始的时候农夫在n;
star.step=0;//次数为0;
vis[star.x]=1;//标记开始的位置走过
q.push(star);//把开始的入队
while(!q.empty())//如果q非空
{
now=q.front();//now定义为队头,第一次的时候也就是star
q.pop();//删除q中队头 ,一定要清空,要不然下一次再要把走的这一步变成当前走的步数就不能用q.pop();
if(now.x==k)//如果此时已经走到了k就输出此时的次数
{
cout<<now.step;
return ;
}
for(int i=0;i<3;i++)
{
//bfs模板
if(i==0)
next.x=now.x+1;
else if(i==1)
next.x=now.x-1;
else if(i==2)
next.x=now.x*2;
if(next.x>=0&&next.x<N&&vis[next.x]==0)
{
vis[next.x]=1;//标记已经走过
next.step=now.step+1;//步数加一
q.push(next);//将此时的存进q,此时下一步的now就是上一步的next了
//有点绕口但是就是用一个queue定义的q来临时存每次的上一步,现在,下一步;
//因为star,now,next都是结构体不能存多个数,就把他们放进q队列里;
}
}
}
}
int main()
{
ios::sync_with_stdio(false);//用cin与cout时这句话提高输入输出的时间;
cin>>n>>k;
bfs();
return 0;
}
Potions (Hard Version)
你是一个病人,要吃药了,当前健康度为0,然后药都放在路上,每个药都有相应的健康值,吃了就会产生相应的变化。现在你在路的左侧,要从左侧走到另一侧,中途不能出现健康度为负的时候,怎么样才能吃最多的药通过这条路呢?
Input
输入第一行是正整数 nn (1 \leq n \leq 2000001≤n≤200000) — 表示有多少药.
第二行是 n 个整数,a_1a1, a_2a2, ... ,a_nan (-10^9 \leq a_i \leq 10^9−109≤ai≤109) 表示这些药的健康值。
Output
输出一个整数,表示你最多能吃多少药。
Example
Input
6 4 -4 1 -3 1 -3
Output
5
Note
在样例中,你吃了4 1 -3 1 -3共5份药,最后健康度为0。
代码:
#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<algorithm>
using namespace std;
int main()
{
long long n,x,i;
cin>>n;
priority_queue<long long,vector<long long>,greater<long long> >q;
//优先级队列greater从小到大排列
//将greater改成less即为从大到小
long long ans=0,sum=0;
while(n--)
{
cin>>x;
if(x>=0)
{
sum+=x;
ans++;
}
else
{
//x是负数的情况
if(x+sum>=0)
{
sum+=x;
ans++;
q.push(x);
}
else if(x+sum<0)//如果当前的值令总和为负数就跟之前存的负数最小的比较
{
if(q.empty())
continue;
else if(x>q.top())//如果x比之前存的最小的负数大就换一下,相当于喝当前的x不喝那瓶小的 ,所付出的代价小
//注意::负数越大喝下它总和减的越少
{
sum-=q.top();//q.top返回第一个值
sum+=x;
q.pop();//删掉第一个数也就是之前最小的那个
q.push(x);//把x存进去 queue自动排序从小到大
}
}
}
}
/*
例如 此时队列中是 -5 -4 -2 -1;
此时x为-3;总和为2 喝下-3后为-1;
-3比-5要大 也就是喝-3比喝-5死的慢
此时 sum=2+5-3 =4;
这样还能继续喝
*/
cout<<ans<<endl;
return 0;
}