谷歌面试题:扔鸡蛋/摔手机

题目与讲解请移步:

https://blog.csdn.net/csdnsevenn/article/details/80971550?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%89%94%E9%B8%A1%E8%9B%8B&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-80971550

 

https://blog.csdn.net/zuochao_2013/article/details/82186101?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159454597119724843336417%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159454597119724843336417&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v3~pc_rank_v2-1-82186101.first_rank_ecpm_v3_pc_rank_v2&utm_term=%E6%89%94%E9%B8%A1%E8%9B%8B

 

【理解:最坏情况的最优策略】

最坏情况,归根结底是只有1个鸡蛋的情况下,需要从“最底层(相对)”一直往上走;显然,如果耐摔度比较低,那么很快就能找到,用的次数比较少。如果耐摔度最高,那么需要最多的次数,这就是所谓的“最坏情况”。

每种策略的“最坏情况下”所需要的的鸡蛋数是固定的。我们仅需要对于特定的鸡蛋数和楼层,找到每种策略、最坏情况的最小值,即为dp[i][j].

 

dp容易出错的地方:

1、谨防每次取min,结果都是0(正确做法应该是先预设res是最大值,这样才可以不断取min,并最终给dp[i][j])。

2、注意边界条件(一般是首行、首列)的初始值设置

 

正确做法:

#include <bits/stdc++.h>
using namespace std;
int dp[1000][100000] = {0};
int main(){
	int n,m;
	cin >> n >> m;
	
    //n是鸡蛋个数,m是楼层数
    //dp[n][m]是每种策略“有n个鸡蛋,测m层楼情况下鸡蛋的耐摔程度”之最坏情况,所用的最小次数
    
	for(int i = 1;i <= n;i++){
		dp[i][1] = 1;
		dp[i][0] = 0;
	}
	
	for(int i = 1;i <= m;i++){
		//dp[0][i] = 0;这句可有可无,因为用不到这一行的数据 
		dp[1][i] = i;
	}
	
	for(int i = 2;i <= n;i++) {
		for(int j = 2;j <= m;j++){
			int res = 1 << 31 - 1 ;//res默认是无穷大 
			for(int k = 1;k <= j;k++){
				res = min( res , 1+max(dp[i-1][k-1],dp[i][j-k]) );
/*要注意,这个 最优 指的是每种策略(每次从第几层往下摔),“最坏情况(用次数最多发现耐摔值)”的最优,我们不知道真正的耐摔系数究竟是多少 
*/
			}
			dp[i][j] = res;
		}
	}
	
	
	printf("%d\n",dp[n][m]);	
	
/*	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			printf("%d  ",dp[i][j]);
			if(j == m)	printf("\n");
		}
	} 
*/ 

} 

注意:

1、i j都写作从2开始,因为从0 1开始的行和列已经被初始化

2、for(int k = 1;k <= j;k++)
                res = min( res , 1+max(dp[i-1][k-1],dp[i][j-k]) );

 

k为什么从1开始而不从0开始?

答:若从0开始,则会和dp[i][j]自身(初始值为0)取min;且k-1会产生索引失败,因为index出现了负数。

       更何况从1到最高层是每种策略可选择的扔掷楼层,符合逻辑。

 

终止条件为什么是k <= j而不是其他?

答:因为如果是 j 层高的楼的话,第一次就从最高层扔也是一种方案。所以k <= j是比较自然的想法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值