每日刷题(四十六)
蓝桥杯第九届C语言B组省赛习题
习题D:测试次数
每次都感觉蓝桥杯出的题目都特别有趣,尤其是背景信息
这个题可以用递推,不能考虑二分法!
我们知道如果只给你一部手机测,也就是说只有一次机会,摔坏了就没办法测了,我们就会采取从第一层逐层往上测,那么最坏的运气就是你手机摔坏的层数,一部手机的情况下就不需要考虑最佳策略了,因为考虑不了
如果给你两部手机测,那么你就有两次机会。我们知道dp[i][2] = d[[i -1][2] + 1,手机测试次数最大值所满足的公式。我解释一下,坏运气就是你要一直测下去,增加测试次数,所以第i层的测试次数就是第i - 1层的测试数据 + 1,在第i层摔没摔坏我们不需要管,而d[i-1][2] + 1中下标为何是2呢,如果你再第i - 1层摔坏了,那你还会往上测吗?
接着考虑最佳策略:
最高楼为j层
在第k层摔:
1)如果摔坏了,则d[k - 1][2 - 1] + 1
2)如果没坏,则继续往上走d[j - k][2] + 1
我们就是要取两种情况中最大次数t,然后再取min(t, d[j][2])
这就是大致思路
详细C代码如下:
#include<stdio.h>
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 dp[1001][3] = {0};
int i, j;
for(i = 1; i < 1001; i++)
dp[i][1] = i; //只有一部手机时从下往上测试最坏测试次数
int k;
for(i = 2; i <= 3; i++)
{
for(j = 1; j <= 1000; j++)
{
dp[j][i] = 1 + dp[j - 1][i]; //dp[i][j]的最大值总是满足dp[i][j]= dp[i-1][j]+1
for(k = 2; k <= j; k++) //因为不知道手机的耐摔指数,一切都从二层开始
{
dp[j][i] = Min(dp[j][i], 1 + Max(dp[k - 1][i - 1], dp[j - k][i]));
} //好坏情况中最大值是最坏运气与dp[i][j]中的最小值便是最佳策略
} //如果在第k层手机摔坏了,则dp[k - 1][i - 1]
//如果在第k层手机没坏,则dp[j - k][i]
}
printf("%d\n", dp[1000][3]);
return 0;
}
运行结果如下:
所以最坏运气下采取最佳策略需要测19次