16年杭电多校赛contest6 1010 Windows 10

                                      Windows 10

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1276    Accepted Submission(s): 434


Problem Description
Long long ago, there was an old monk living on the top of a mountain. Recently, our old monk found the operating system of his computer was updating to windows 10 automatically and he even can't just stop it !!
With a peaceful heart, the old monk gradually accepted this reality because his favorite comic LoveLive doesn't depend on the OS. Today, like the past day, he opens bilibili and wants to watch it again. But he observes that the voice of his computer can be represented as dB and always be integer.
Because he is old, he always needs 1 second to press a button. He found that if he wants to take up the voice, he only can add 1 dB in each second by pressing the up button. But when he wants to take down the voice, he can press the down button, and if the last second he presses the down button and the voice decrease x dB, then in this second, it will decrease 2 * x dB. But if the last second he chooses to have a rest or press the up button, in this second he can only decrease the voice by 1 dB.
Now, he wonders the minimal seconds he should take to adjust the voice from p dB to q dB. Please be careful, because of some strange reasons, the voice of his computer can larger than any dB but can't be less than 0 dB.
 


 

Input
First line contains a number T(1 <= T <= 300000),cases number.
Next T line,each line contains two numbers p and q (0 <= p,q <= 1e9)
 


 

Output
The minimal seconds he should take
 


 

Sample Input
  
  
2 1 5 7 3
 


 

Sample Output
  
  
4 4
 

 

这是一道神奇的题目,我表示当时其实大概明白怎么做了,但是一直wa一直wa,里面好几个变量进入递归过程的时候我控制不好,思维不清晰导致很晕。实在是混得不行,我还是默默的看了标程。。。标程十分简短,就十行多,清晰易懂,所以说,优美的代码是成功AC的第一步。

题意就是,要求P到Q的最小秒数。这个过程中有一个要点,1,上升的话只能一个一个上升,2,连续下降的话,本一次的下降量是上一次的2倍,也就相当于1,2,4,8这样减下去,但是这个是可以中断的,你可以选择休息一秒,那么下降量就归零,也可以选择上升一格,清空下降量。其中有个关键就是,比如你现在是7,下一次是下降8,那么不会变成-1,而是会变成0的。

这道题第一次看到的时候,默认想到的是BFS,但是BFS冗余量太大,会完美超时,分析分析看看,Q大于P的话,直接相减输出。P>Q下降的话,其实只有两种走法,一种是下降到恰好比Q小,然后往回升,一种是下降到恰好比Q大,清除一下下降量,再下降,这样循环。所以我们可以用递归来写,用DFS。每次下降到恰好比Q小,算一下加上上升所需要的步数,与Min比较一下。得到恰好比Q大的数字,进入下一次递归。

你需要去记录停顿了多少次,因为你停顿的时候是浪费掉的,还不如去补偿上升的步数呢,因为你上升也是可以消除下降步数的。

所以,代码如下,还是很乱的,在原来wa的代码上修改一下就过了哭

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<set>
using namespace std;
int p,q,k;
long long Min;

void dfs(long long x,int n)
{
	int i = 0;
	int t = 1;
	long long sum = 1;
	int cout, add;
	if(x - sum == q)//如果恰好等于了,就可以直接返回结束了 
	{
		if(n + 1 < Min)//以前所经过的次数n次加上执行了i+1次就是这次所使用的次数 
			Min = n + 1;
		return;
	}
	while(x - sum > q)//使劲往下降,等于的话会在循环内检测出来,如果小于的话就跳出
	{
		t *= 2;
		i++;//说明t是2的i次方
		sum += t;		
	}
	
	if(x - sum < 0)//如果x-sum小于了0,那么就会自动变成0,所增加的次数就是q减去0
		add = q - 0;
	else//如果没有小于0,那就可以直接算出q和(s-sum)的差 
		add = q - (x - sum);
	add = add - k <= 0 ? 0 : add - k;
	cout = add + i + n + 1;//总共的次数 
	if(cout < Min)
		Min = cout;
	k++;//这个是停顿的次数
	dfs(x - (sum - t), n + i + 1);//i+1是这次循环所用的次数
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d", &p, &q);
		if(p <= q)
			printf("%d\n",q - p);
		else
		{
			Min = 99999999;
			k = 0;
			dfs(p, 0);
			printf("%lld\n",Min);
		}
	}
	return 0;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值