测试次数 第八届蓝桥杯省赛(dp)

测试次数

x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。

x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。

如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。
如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n

为了减少测试次数,从每个厂家抽样3部手机参加测试。

某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?

请填写这个最多测试次数。

注意:需要填写的是一个整数,不要填写任何多余内容。
答案:19。
思路:本题源自于一道谷歌经典的面试题,如果在第一次接触就能够做出来的,绝对是大神--------------------------------------------------------------------------------首先,假设我们有N部手机,M层楼。那么题意要求我们在刚好摔坏N部手机时恰好测试出手机的抗摔系数,(采用最优策略)即此时我们测试次数的最小值是多少。注意,这里的意思是,因为我们选择测试楼层的策略的原因,在N部手机M层楼的情况下,测试任何抗摔系数的手机的次数都不大于我们所求的次数。这里,我们采用动态规划的做法。显然,如果我们只有一部手机,那么无论如何,我们都老老实实的要从第一层开始向上摔,即dp[1][j]=j. 当我们手中的手机数量大于1的时候,我们便可以考虑开始在不同的楼层测试抗摔系数。我们假设答案为k次,那么显然,第一次的时候我们需要站在第k层楼摔。假如此时我们手里的手机摔坏了,那么我们还剩下n-1部手机,测试k-1层楼;假如我们没有摔坏,那么我们还有n部手机,测试j-k层楼。
代码:

#include <stdio.h>
int dp[5][1005],k;  //我们假设第一次站在k层楼摔 
//dp[i][j]代表有i部手机j层楼时摔坏所有手机的情况下 测试任意抗摔系数的最多次数 
//dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k)); 
//状态转移方程表示 :1.不同k之间取最小值 2.同一k之间的不同情况取最大值,避免遗漏(如果在这里取了最小值,那么意味着需要更多测试次数情况的测试不到) 
//dp[i][j-k]表示还剩下j-k层楼没有测试,在这里不要想当然的认为楼层越高越容易摔碎,我们需要的只是能测试所有的楼层即可 
int min(int x,int y)
{
	return x<y?x:y;
}
int max(int x,int y)
{
	return x>y?x:y;
}
int main()
{
	for(int i=1;i<=3;i++)
	{
		for(int j=1;j<=1000;j++)
		{
			dp[i][j]=j;   //初始化
		}
	 } 
	 for(int i=2;i<=3;i++)
	 {
	 	for(int j=2;j<=1000;j++)
	 	{
	 		for(int k=1;k<=j;k++)
	 		{
	 			dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k])+1);
			 }
		 }
	 }
	 printf("%d",dp[3][1000]);
	return 0;
 } 
 
发布了31 篇原创文章 · 获赞 11 · 访问量 2580

猜你喜欢

转载自blog.csdn.net/guyjy/article/details/104754710