第九届蓝桥杯 测试次数/ 耐摔指数 DP代码讲解

测试次数 / 耐摔指数

在这里插入图片描述

题目提交点

点我进入官方提交点

题目思路讲解

  • 先从数据入手,简单的模拟一下

以第三层,三个手机为例:
从第一层开始摔:
如果该层手机完好,那么按照运气不好的情况,后面两层也是手机完好,一共三次。
如果该层手机摔坏,直接测出来,一共一次。
所以从第一层开始摔,最多测试三次。

从第二层开始摔:
如果该层手机完好,那么按照运气不好的情况,后面一层好或不好,一共都是两次。
如果该层手机摔坏,那么按照运气不好的情况,前面一层好或不好,一共也都是两次。
所以从第二层开始摔,最多测试两次。

从第三层开始摔:
如果该层手机完好,直接出答案,一共一次。
如果该层手机摔坏,最坏情况下,下面两层都把手机摔坏了,手机损失3个,一共三次。
所以从第三层开始摔,最多测试三次。

然后一总结得出最多结果为两次。

  • 总结,发现规律

手机的测试次数受到手机个数和层数的影响,每一次比对都没有固定的规律,不知道哪一种策略是最好的,有点偏向于动态规划,所以尝试着使用DP的思想去做这个题目。

  • 分析DP
  1. 发现最优子结构性质

以好坏进行进行划分,将其化为两个部分进行比较,将手机向下摔,如果是好的,那么就往上面走,如果是坏的,那么就我往下面走,对两边取大的那一方。

  1. y a n 氏 D P 图 yan氏DP图 yanDP

集合表示:剩余i层j台手机最坏情况下的测试次数。(往上走摔手机和往下走摔手机是相互独立的,没有互相干扰,而且具有重叠子问题性质,所以使用关键字”剩余“来表示集合)。
属性:每一次都是采用最佳策略,所以是取最小值。

状态划分:以从哪一层开始摔,摔的好坏作为划分依据。

在这里插入图片描述

  • 数据初始化

只有一台手机的话,最坏情况下是从第一层开始摔,直到楼顶,还是好的,所以要初始化一台手机的情况。

AC代码

#include<bits/stdc++.h>
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << endl;
#define mod(x) (x) % MOD
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 10000 + 10;
int f[N][4];

int main()
{
#ifdef LOCAL
    freopen("data.in", "r", stdin);
#endif
    ios::sync_with_stdio(false); // 取消cin与stdin 的同步
    cout.tie(0), cin.tie(0);

    int m = 3, n;
    cin >> n;
    
    _rep(i, 1, n) f[i][1] = i;
    _rep(i, 1, n) _rep(j, 2, m) {
        f[i][j] = 0x3f3f3f3f;
        _rep(k, 1, i)
            f[i][j] = min(f[i][j], max(f[k - 1][j - 1], f[i - k][j]) + 1);
    }

    cout << f[n][m] << endl;
    return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值