#include
#include<string.h>
#include<queue>
using namespace std;
int k,a[100001];
struct list
{
int n,t;
}next,now;
int bfs(int n,int t)
{
if(n==k)
return 0;
queue<list> q;
now.n=n;
now.t=t;
a[n]=1;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
if(now.n-1==k||now.n+1==k||now.n*2==k)
{
return now.t+1;
}
if(now.n-1>0&&!a[now.n-1])
{
next.n=now.n-1;
next.t=now.t+1;
a[now.n-1]=1;
q.push(next);
}
if(now.n+1<k&&!a[now.n+1])
{
next.n=now.n+1;
next.t=now.t+1;
a[now.n+1]=1;
q.push(next);
}
if(now.n!=0&&now.n*2<1e5&&!a[now.n*2]&&now.n*2-k<k-now.n)
{
next.n=now.n*2;
next.t=now.t+1;
a[now.n*2]=1;
q.push(next);
}
}
}
int main()
{
int cnt,n;
scanf(“%d%d”,&n,&k);
memset(a,0,sizeof(a));
cnt=bfs(n,0);
printf(“%d\n”,cnt);
return 0;
}
#include<stdio.h>
#include<queue>
using namespace std;
int k;
struct list
{
int n,t,b;
}next,now;
int bfs(int n,int t)
{
if(n==k)
return 0;
queue<list> q;
now.n=n;
now.t=t;
now.b=0;
q.push(now);
while(now.n-1!=k&&now.n*2!=k&&now.n+1!=k)
{
if(now.b!=2&&now.n-1>=0)
{
next.n=now.n-1;
next.t=now.t+1;
next.b=1;
q.push(next);
}
if(now.n+1<k&&now.b!=1)
{
next.n=now.n+1;
next.t=now.t+1;
next.b=2;
q.push(next);
}
if(now.n*2-k<k-now.n&&now.n*2<=1e5&&n!=0)
{
next.n=now.n*2;
next.t=now.t+1;
next.b=0;
q.push(next);
}
now=q.front();
q.pop();
}
t=now.t+1;
return t;
}
int main()
{
int cnt,n;
scanf("%d%d",&n,&k);
cnt=bfs(n,0);
printf("%d\n",cnt);
return 0;
}
对比上面两种,前者与后者有很大区别,这区别便是bfs
前者在讲一个点列入数列的时候是要判断列入的点是否已经没有列入的必必要了(越界,已经列过了,now.n与k的关系)而后者即是没有把重复了列入分开,虽然判断了前一个与后一个的关系(上一个减一后一个加一这种情况但是)对于再远的情况你并未能进行完全的排除(翻倍后与n+1已经这种与-1的组合)所以bfs的学习应注意细节。
poj 3278