AcWing1048 鸡蛋的硬度(浅谈两种解法的思考方向)

这是经典的谷歌面试题,也是经典的动态规划问题

根据y总的说法,动态规划问题要划分集合,表示状态

对于这道题,有两个经典的解法,他们的复杂度不同,因为对状态的定义略有不同

1.最常规的思想,设计状态为前i层用j个鸡蛋所能测的最坏情况的最小值是多少

我相信集合的定义很多人能想到,但是状态的定义还需要进行分析

首先,为什么是最坏情况,因为我们不知道鸡蛋什么时候会碎,这是未知的,所以要考虑最坏的情况,而最小值是因为,这是我们能控制的。

所以不能控制的要考虑最坏,能控制的要考虑最好

那么状态转移方程就能定义为f[i][j-1]和max(f[i-k][j],f[k-1][j-1]]+1中的最小值,因为我们在考虑测试的时候,可以在1-i中任选一个地方开始测,但是我们不能知道在我们选的地方蛋会不会碎

另外,还可以不适用鸡蛋,也就是直接沿用f[i][j-1]的情况

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int f[N][N];
int main(){
    int i,j;
    int n,m;
    while(cin>>n>>m){

    for(i=1;i<=n;i++){
        f[i][1]=i;
    }
    for(i=1;i<=m;i++){
        f[1][i]=1;
    }
    for(i=2;i<=n;i++){
        for(j=2;j<=m;j++){
            f[i][j]=f[i][j-1];
            int k;
            for(k=1;k<=i;k++){
                f[i][j]=min(f[i][j],max(f[i-k][j],f[k-1][j-1])+1);
            }
        }
    }
    cout<<f[n][m]<<endl;}
}

2.上面的复杂度比较高,那是因为我们要选一个地方进行测试,所以要多枚举一维。第二种方法更加巧妙

我们定义f[i][j]为用j个鸡蛋测量i次最多能测多长的区间,我们能想到这个状态的原因是,动态规划的划分依据一般从题目所给信息想出,我们既然不想枚举位置,那么就把长度当作状态量,而把次数和个数当作状态。

这样的话就能用f[i-1][j-1]+f[i-1][j]+1,这个意思是,如果蛋碎了,那就是测i-1次用j-1个鸡蛋的长度,不然就是i-1次用j个鸡蛋的长度,因为蛋的情况只有一种,所以两个集合独立,可以相加,而他们相加就是最终的答案

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int f[N][N];
int main(){
    int i,j;
    int n,m;
    while(cin>>n>>m){
        for(i=1;i<=n;i++){
            for(j=1;j<=m;j++){
                f[i][j]=f[i-1][j]+f[i-1][j-1]+1;

            }
            if(f[i][m]>=n){
                    cout<<i<<endl;
                    break;
            }
        }
    }
}

原文地址:https://www.cnblogs.com/ctyakwf/p/12641124.html

时间: 2024-11-23 12:18:54

AcWing1048 鸡蛋的硬度(浅谈两种解法的思考方向)的相关文章

浅谈两种方法实现浏览器内多个标签页之间的通信

调用localstorge.cookies等本地存储方式. 方法一: localstorge在一个标签页里被添加.修改或删除时,都会触发一个storage事件,通过在另一个标签页里监听storage事件,即可得到localstorge存储的值,实现不同标签页之间的通信. <input id="name"> <input type="button" id="btn" value="提交"> <scr

hdu 4521 小明系列问题——小明序列 (间隔至少为d的LIS 两种解法)

先附上资源地址:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握. 最近,我读到一篇材料,发现有一个很好的类比,可以把它们解释地清晰易懂. 1. 计算机的核心是CPU,它承担了所有的计算任务.它就像一座工厂,时刻在运行. 2. 假定工厂的电力有限,一次只能供给一个车间使用.也就是说,一个车间开工的时候,其他车间都必须停工

POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法

题意:将一个无向图中的双向边改成单向边使图强连通,问最多能改多少条边,输出改造后的图. 分析: 1.双连通做法: 双连通图转强连通图的算法:对双连通图进行dfs,在搜索的过程中就能按照搜索的方向给所有边定向,其中桥不能改造,只能保留双向边. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #includ

求最大公约数的两种解法(欧几里得算法和素数分解)

最大公约数的两种解法(欧几里得算法和素数分解) 方法一: 欧几里得算法,又称辗转相除法 定理(欧几里得算法):设a和b是正整数,则存在最大求最大公因子d=(a,b)的一种算法,且存在求一组整数s,t使得d = sa+tb 举个例子:求168和60的最大公约数? 168 = 2 * 60 + 48 60  = 1 * 48 +12 48  = 4 * 12 由此得最大公约数为12 关于最大公倍数 C语言程序代码:很简单就不加注释了 #include<stdio.h> #define SWAP(a

POJ 3628 Bookshelf 2 0/1背包和DFS两种解法

题目链接:POJ 3628 Bookshelf 2 Bookshelf 2 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7462   Accepted: 3436 Description Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly,

统计逆序对的两种解法

统计逆序对的两种解法 归并排序(mergeSort) 逆序对定义 \(i<j\) 但\(a[i]>a[j]\),假设我们分别使得通过mergeSort使得左右半边有序 即\(a[1]...a[mid]\) 递增, \(a[mid+1]....a[n]\)递增,我们需要通过merge操作,完成整个的排序和新增逆序对的计数,较小值出现在左半边记为 a[i],出现在右半边即为 a[j],那么每次出现在右半边,意味左半边比a[i]大的数都比a[j]大,由此可以统计逆序对 HDU1394 代码实现 #i

涨姿势题2_水题_两种解法

Problem Description 涨姿势题就是所谓的优化题,在组队赛中,队伍发现了一题水题,那么应该交给谁去处理?作为处理水题的代码手,应该具备什么样的素养?1,要快,水题拼的就是速度!2,不能卡水题!水题都卡,绝对不是一个代码手的风范!3,不能出错,错一次即罚时20分钟,对于水题来讲是致命的!4,要能看出来一题是水题!没有这条,上面三条都是没有意义的! 如果你希望你成团队中一个合格的代码手,那么这套题是你最好的选择,快AC吧! 本系列即是为了提高水题代码手的素养而准备的!水题经常需要用到

ZOJ3822 ACM-ICPC 2014 亚洲区域赛牡丹江赛区现场赛D题Domination 概率DP(两种解法)

题目地址:点击打开链接 这道题有两种做法,第一种是直接求期望,类似于poj 2096 区别在于这个步数有限.所以要迭代步数. #include <cstdio> #include <cstring> #include <iostream> #define maxn 55//这里刚开始写成了50+10 那么maxn*maxn就会小很多wa了一次 using namespace std; double dp[maxn][maxn][maxn*maxn]; int N,M,T

Letter Combinations of a Phone Number:深度优先和广度优先两种解法

Letter Combinations of a Phone Number Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Input:Digit string "23" Outpu