HDU 5802

HDU 5802

题意:

三种操作使 p 变为 q;
1)休息,什么也不做 ;
2) 让 p 加 1 ;
3)让 p 减 1 ,如果上一次操作减去了 x ,那么这一次会减去 2 * x ;
如果上一次的操作是 休息 或者 加 1 ,那么只能让 p 减 1;

求最少的操作数 。

 

解题:

自己先开始模拟没模出来...

看题解写的,我的理解是酱紫的

p 可以减的数是 1 2 4 8 ... 如果连续减 x 次的话也就是 (2^x)-1 ;
先让 p 减到当前最靠近的 q 的位置 ,此时 p 是 p<=q 的;
如果恰好 p == q ,那么就可以返回结果了;
如果没有,那就选择是减到 p <= q 再加回来,还是休息再继续从 1 开始减;
因为休息和加 1 都可以让 p 从 1 开始减,所以如果有 加的操作
那么之前停的次数就可以不算了。

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dfs(ll s, ll e, ll ste, ll sto)
{
    if(s == e) return ste;
    ll x = 0 ;
    while(s - (1<<x) + 1 > e) x++;
    if( s - (1<<x) + 1 == e) return ste + x;
    ll up = e - max((ll)0,  s - (1<<x) + 1 ) ; // 
    ll ano = x + max((ll)0, up-sto);
    return min(ano+ste, dfs( (s - (1<<(x-1)) + 1 ), e, ste+x, sto+1 ) );
} 
int main()
{
    int t;
    ll p,q;
    scanf("%d",&t);
    while(t--) {
        scanf("%I64d%I64d",&p,&q);
        if( p <= q ) {
            printf("%I64d\n",q-p); continue;
        }
        ll ans = dfs(p,q,0,0);
        printf("%I64d\n",ans);
    } 
    return 0;
}

 

posted @ 2016-08-05 16:03  Ember  阅读(223)  评论(0编辑  收藏  举报