题意是在一个数轴上,每次可以一步到达当前位置数值的 2 倍的位置或者数值 +1 或数值 -1 的位置,给定 n 和 k,问从数值为 n 的位置最少多少步可以到达数值为 k 的位置。
用广搜的方法,把已经到达的位置标记,检查三个方向(*2,+1,-1)的位置是否到达 k,如已经到达就返回遍历的层数,否则将新的位置标记,继续检查新位置的三个方向。
这题要注意剪枝,每次的新位置要大于 0 小于 1e6,且当 n 大于 k 的时候要特殊处理,此时只能通过 -1 的方法到达 k,故输出 n - k 即可。
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int n,k,cnt,a[100005]; 5 bool vis[100005]; 6 int bfs(int from,int times) 7 { 8 9 int ccnt = cnt; 10 for(int i = from; i < ccnt; ++i) 11 { 12 if(a[i]*2==k || a[i]+1==k || a[i]-1==k) 13 return ++times; 14 else 15 { 16 if(a[i]*2<=100000&&(!vis[a[i]*2])) 17 { 18 a[cnt++] = a[i]*2; 19 vis[a[i]*2] = 1; 20 } 21 if(a[i]-1>=0&&(!vis[a[i]-1])) 22 { 23 a[cnt++] = a[i]-1; 24 vis[a[i]-1] = 1; 25 } 26 if(a[i]+1<=100000&&(!vis[a[i]+1])) 27 { 28 a[cnt++] = a[i]+1; 29 vis[a[i]+1] = 1; 30 } 31 } 32 } 33 return bfs(ccnt,++times); 34 } 35 int main() 36 { 37 while(~scanf("%d %d",&n,&k)) 38 { 39 if(n==k) 40 puts("0"); 41 else if(n>k) 42 printf("%d\n",n-k); 43 else 44 { 45 cnt = 1; 46 a[0] = n; 47 memset(vis,0,sizeof(vis)); 48 vis[n] = 1; 49 printf("%d\n",bfs(0,0)); 50 } 51 } 52 return 0; 53 }