機智的csy

【簡要題面】現在你在數軸上的座標爲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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章