题意:一条线上两个点n和k,k点不动,n点可以移动,有三种移动方法,向左移动一位,向右移动一位,和向右移动到当前位置的下标的两倍位置、即2*pos处;
n、k<=100000;
解:可以通过bfs(广度优先收索来做)注意vis的作用是来减少重复的访问某个节点,不设的化会超时!!
当k<=n时显然步数为n-k步
当k>n时bfs()
ac代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k;
int step[300005]; //计入当前步数
int cnt; //计入最后结果
int vis[300005];
void bfs()
{
memset(step,0,sizeof(step));
memset(vis,0,sizeof(vis));
queue<int > q;
q.push(n);
vis[n] =1;
while(!q.empty())
{
int tp = q.front();
q.pop();
for(int i=0;i<3;i++)
{
if(i==0)
{
int next = tp-1;
if(next>=0&&next<=2*k&&!vis[next])
{
vis[next]=1;
step[next] = step[tp] +1;
if(next==k)
{
cnt = step[next];
return;
}
q.push(next); }
}
if(i==1)
{
int next = tp+1;
if(next>=0&&next<=2*k&&!vis[next])
{
vis[next] =1;
step[next] = step[tp] +1;
if(next==k)
{
cnt = step[next];
return;
}
q.push(next);
}
}
if(i==2)
{
int next = tp*2;
if(next>=0&&next<=k*2&&!vis[next])
//对于为什么要<=2*k,我是这样想的又没用一种情况,n要先*2在减去某个值才等于k所以next的值可能会大于k,所以2*k保证了这
//种情况,不过看其他的题解好像直接<=k也可以ac -_-
{
vis[next]=1;
step[next] = step[tp] +1;
if(next==k)
{
cnt = step[next];
return;
}
q.push(next);
}
}
}
}
return;
}
int main()
{
scanf("%d%d",&n,&k);
if(k<=n)
{
printf("%d",n-k);
}
else
{
bfs();
printf("%d",cnt);
}
return 0;
}