OpenJudge 2.5-2971 Catch That Cow(抓住那头牛)
Description
Input
Output
Sample Input
Sample Output
最后再说明一下,这里计算步数的时候相当于是找出了所有路径,但是这里只要求所走步数,可以直接用pre[tail]=head+1;就可以了
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
两个整数,N和K
一个整数,农夫抓到牛所要花费的最小分钟数
5 17
4
这是我做广搜的第一道题,虽然搜索都学完了 ,我们来看一看广搜应该怎么写吧
广搜要运用到队列的思想,这里我是用的数组来模拟队列,当然用队列做就更不成问题了。
这道题要是用深搜写,很有可能像个无底洞一样,一直都搜不到。别废话了,要是用深搜做广搜题,百分之一百的TLE。所以与深搜不同,广搜优先拓展“宽度”,打个不是很恰当的比方,深搜就是考一门科目,拿100分,广搜就是考八门科目,考60分。
我们先来画个图
(图渣求放过)
我们先来分析一下这幅图(好吧我知道这渣图你们可能什么都看不出来,但看在我辛辛苦苦画的份上就暂且一看),广搜就是不停地拓展树的宽度,先访问完同一层的结点之后再访问下一层。针对这道题而言呢,农夫有三种前进的方式,每一种可以产生一个结点,直至出现了目标结点之后,目标结点的层数就是农夫所走的步数。过程中要标记已经访问过的结点,不再拓展,因为前面已经拓展过这个结点了,再拓展即使得到了解也不是最优解了。
程序我们仍然可以按照框架来写,广搜已经写过框架了,这里就不再赘述,代码奉上(含注释):
#include<cstdio>
#include<cstdio>
int que[1000000],pre[1000000],n,k,next;//que队列,pre前驱
bool mark[1000000];//标记访问过的结点
void print(int x)//根据前驱找父亲结点,计算步数
{
int sum=0;
while(pre[x])
{
sum++;
x=pre[x];
}
printf("%d",sum);
}
void bfs()
{
if(n==k) {printf("0"); return;}//坑点,如果农夫一开始就在奶牛的位置,输出0
int head=0,tail=1;//队列初始化
que[1]=n;//队头入队,并标记
mark[n]=1;
while(head!=tail)
{
head++;//队列中的下一个元素作为父结点拓展子结点
for(int i=1;i<=3;i++)//拓展子结点
{
if(i==1) next=que[head]+1;
if(i==2) next=que[head]-1;
if(i==3) next=que[head]*2;//三种前行方式
if(next<=1000000&&next>=0&&!mark[next])//next<=1000000是为了避免陷入死循环而根据数据范围设定的
{//next>0为了防止出现负数,负数不能作为数组下标,否则会RE,且mark没有被标记过
tail++;//队尾指针加1,标记入队
que[tail]=next;
mark[next]=1;
pre[tail]=head;
if(next==k) //找到目标结点
{
print(tail);
head=tail;//强制退出while
break;//退出for
}
}
}
}
}
int main()
{
scanf("%d %d",&n,&k);
bfs();
}
最后再说明一下,这里计算步数的时候相当于是找出了所有路径,但是这里只要求所走步数,可以直接用pre[tail]=head+1;就可以了
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com