第九届蓝桥杯B组第四题--测试次数(C语言)

第九届蓝桥杯B组第四题–测试次数(C语言)

一.比赛题目

1.题目要求

x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n;为了减少测试次数,从每个厂家抽样3部手机参加测试。
某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?

2.输入与输出

输出:
填写最多测试次数;

二.分析过程

答案为:19

1.方法分析

我想很多人最开始和我一样都会想用二分法来做这个题,但是二分的话,500层一摔手机碎了,250碎了,125碎了;然后三个手机碎完,我们都不知道手机耐摔指数;
而这道题和区间动态规划特别像,所以就用动态规划的方法来做。

2.做题思路

假如动态规划的话,我们首先确定状态变量:

i楼层数
j手机数
k机会数

假如我们有k次机会来砸的话:

碎了
碎了
k层楼来砸
还剩j-1部手机 k-1层楼
还剩j部手机 i-k层楼

我们来小数目填表:

手机数\楼层1234
11234
21
31

因为一部手机的话只能一层楼一层楼来砸,而一层楼的话显然只需要砸一次,所以这个时候我们也把动态规划的边界写出来了(如上表所示);
我们通过上面流程图的分析也可以知道他的状态转移方程如下:

dp[i][j]=min(dp[i][j],max(dp[k-1][j-1],dp[i-k][j])+1);

为什么要用min比较一次?
因为题目中说的是最多,也就是求每次dp[i][j]可能次数里面最小的;

3.核心代码

for(int i=1;i<=n;i++)
		for(int j=2;j<=m;j++)
			{
				dp[i][j]=dp[i][j-1];
//先把dp[i][j]赋值为前一种手机的相同楼层数的最多所需次数
//因为手机比前面多的情况下,最坏情况也不会超过前一种情况
				for(int k=1;k<=i;k++)
//砸的机会数不会大于楼层数
					dp[i][j]=min(dp[i][j],max(dp[k-1][j-1],dp[i-k][j])+1);
			}

三.完整代码

#include<stdio.h>
#include<string.h>
int dp[1010][1010];
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b)
{
	return a<b?a:b;
}
int main()
{
	int n=1000,m=3;
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++)
		dp[i][1]=i;
	for(int i=1;i<=m;i++)
		dp[1][i]=1;
	for(int i=1;i<=n;i++)
		for(int j=2;j<=m;j++)
			{
				dp[i][j]=dp[i][j-1]; 
				for(int k=1;k<=i;k++)
					dp[i][j]=min(dp[i][j],max(dp[k-1][j-1],dp[i-k][j])+1);
			}
	printf("%d",dp[1000][3]);
	return 0;
}

四.总结

这个代码还没有去优化他的时间复杂度和空间复杂度,这道题也和动态规划里面的砸鸡蛋就一模一样的。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值