【简要题面】现在你在数轴上的坐标为x,你需要到坐标y。现在有两种操作:
1.先前或向后一步
2.坐标*2
现在求最小的操作数。数轴长度<=1e5。
【分析】
数轴不长所以可以随便乱搞,dp,bfs或者像我乱spfa都可以。
【code】
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+1000;
int n,k;
int f[maxn];
struct Queue{
int l,r;
int q[maxn];
void push(int x){q[r++]=x;if(r>=maxn) r=r-maxn;}
void pop(){l++;if(l>=maxn)l=l-maxn;}
int front(){return q[l];}
bool empty(){return l==r;}
}q;
bool inq[maxn];
int main(){
while(~scanf("%d%d",&n,&k)){
memset(f,0x7f,sizeof(f));
f[n]=0,q.push(n),f[0]=n;
while(!q.empty()){
int u=q.front();q.pop();inq[u]=0;
for(int i=u-1;i>=1;i--){
if(f[i]<=f[u]+(u-i))break;
else{
f[i]=f[u]+(u-i);
if(!inq[i])inq[i]=1,q.push(i);
}
}
for(int i=u+1;i<=k;i++){
if(f[i]<=f[u]+(i-u)) break;
else{
f[i]=f[u]+(i-u);
if(!inq[i])inq[i]=1,q.push(i);
}
}
for(int i=1;(u<<i)<=k<<1;i++){
if(f[u<<i]<=f[u]+i) break;
else{
f[u<<i]=f[u]+i;
if(!inq[u<<i])inq[u<<i]=1,q.push(u<<i);
}
}
}
cout<<f[k]<<endl;
}
return 0;
}
【dp写法】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
int f[100010];
int main()
{
// freopen("meet.in","r",stdin);
// freopen("meet.out","w",stdout);
memset(f,0,sizeof(f));
scanf("%d %d",&n,&k);
f[n]=1;
for(int i=n-1;i>=0;i--)
f[i]=f[i+1]+1;
for(int i=n+1;i<=k;i++){
if(i%2==0) f[i]=min(f[i/2]+1,f[i-1]+1);
else f[i]=min(f[(i+1)/2]+2,f[i-1]+1);
}
printf("%d",f[k]-1);
return 0;
}