MYF

HDU 5802 Windows 10

题目链接

HDU 5802

题目类型:贪心 + 模拟

题目来源:2016 Multi-University Training Contest 6

题目分析

题目大意

老和尚要从光标的第p行转移到第q行。他上移光标是一秒钟一个格子向上移动,向下是加倍下移,比如第一秒下降一个行,第二秒下降两行,第三秒下降四行,当下降的最后一秒之后,老和尚可以选择停顿一秒,或者选择向上移动一行,问老和尚最少需要多少时间才能将光标从第p行转移到第j行

解析

首先先分析光标应该向上走还是应该向下走,如果向上走直接输出行间距即可。如果向下走的话,我们可以先假设每一次下降之后都停顿,并且记录下来该过程的所有停顿次数。那么我们每次下降的临界条件一定是再下降就比q低了,也就是再下降一秒之后就小于等于q的高度,如果我们恰好到达第q行,那么直接返回到达这一行所需要的时间即可。否则则在q之下,我们可以假设那些停顿的时间都是往上走的,这样可以抵消掉一部分比q低之后再往上的移动时间,假设我们新到达的点的高度为k,我们所有停顿的时间为s,也就是说如果这些停顿的时间全部向上走,我们可以向上走s步,我们到达k之后想要上升到q,我们如果从这s步中取出来一部分t(0<=t<=s)补贴过去,那么我们上升需要的时间即为(q-k)-min(q-k, s),此时达到最优解,然后用这部分上升的时间加上之前下落的时间即为最优解。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <bitset>
#include <cstring>
#include <iostream>
#include <deque>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define PB push_back
#define MP make_pair
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define IN freopen("input.txt","r",stdin);
#define OUT freopen("output.txt","w",stdout);
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#define debug2(x,y) cout<<"Debug : ---"<<x<<" , "<<y<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
ll p,q,cnt;
ll bits[50];
ll work(ll st,ll ed, ll stop,ll step){
if (st<=ed) return ed- st+step ;
int k = 0;
while (st - bits[k] > ed) k++;
if (max(st - bits[k], 0LL) == ed) return k+step;
ll up = ed - max(0LL, st - bits[k]);
ll tmp = step + k + max(0LL, up - stop);
return min(tmp, work(st - bits[k-1], ed, stop + 1, step + k));
}
int main(){
for (int i=1; i<32; i++)
bits[i] = 1LL<<(i-1);
for (int i = 1; i<32; i++)
bits[i]+=bits[i-1];
int t;
scanf("%d",&t);
while (t--) {
cnt =0 ;
scanf("%lld%lld",&p,&q);
printf("%lld\n",work(p, q, 0, 0));
}
}