分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程

package live.every.day.ProgrammingDesign.CodingInterviewGuide.Other;/*** 丟棋子问题** 【题目】* 一座大楼有0~N层,地面算作第0层,最高的一层为第N层。已知棋子从第0层掉落肯定不会摔碎,从第i层掉落可能会摔碎,也可能不会* 摔碎(1≤i≤N)。给定整数N作为楼层数,再给定整数K作为棋子数,返回如果想找到棋子不会摔碎的最高层数,即使在最差的情况下扔* 的最少次数。一次只能扔一个棋子。** 【举例】* N=10,K=1。* 返回10。因为只有1棵棋子,所以不得不从第1层开始一直试到第10层,在最差的情况下,即第10层是不会摔坏的最高层,最少也要扔* 10次。** N=3,K=2。* 返回2。先在2层扔1棵棋子,如果碎了,试第1层,如果没碎,试第3层。** N=105,K=2。* 返回14。* 第一个棋子先在14层扔,碎了则用仅存的一个棋子试1~13。* 若没碎,第一个棋子继续在27层扔,碎了则用仅存的一个棋子试15~26。* 若没碎,第一个棋子继续在39层扔,碎了则用仅存的一个棋子试28~-38。* 若没碎,第一个棋子继续在50层扔,碎了则用仅存的一个棋子试40~49。* 若没碎,第一个棋子继续在60层扔,碎了则用仅存的一个棋子试51~59。* 若没碎,第一个棋子继续在69层扔,碎了则用仅存的一个棋子试61~68。* 若没碎,第一个棋子继续在77层扔,碎了则用仅存的一个棋子试70~76。* 若没碎,第一个棋子继续在84层扔,碎了则用仅存的一个棋子试78~83。* 若没碎,第一个棋子继续在90层扔,碎了则用仅存的一个棋子试85~89。* 若没碎,第一个棋子继续在95层扔,碎了则用仅存的一个棋子试91~94。* 若没碎,第一个棋子继续在99层扔,碎了则用仅存的一个棋子试96~98。* 若没碎,第一个棋子继续在102层扔,碎了则用仅存的一个棋子试100、101。* 若没碎,第一个棋子继续在104层扔,碎了则用仅存的一个棋子试103。* 若没碎,第一个棋子继续在105层扔,若到这一步还没碎,那么105便是结果。** 【难度】* 困难** 【解答】* 方法一。假设P(N,K)的返回值是N层楼有K个棋子在最差情况下扔的最少次数。* 1.如果N==0,也就是楼层只有第0层,那不用试,肯定不碎,即P(0,K)=0。* 2.如果K==1,也就是楼层有N层,但只有1个棋子了,这时只能从第1层开始试,一直试到第N层,即P(N,1)=N。* 3.以上两种情况较为特殊,对一般情况(N>0,K>1),我们需要考虑第1个棋子从哪层楼开始扔一次,如果第1个棋子从第i层开始扔,* 有以下两种情况:* 1)碎了。那么可以知道,没有必要去试第i层以上的楼层,接下来的问题就变成了还剩下i-1层楼,还剩下K-1个棋子,所以总步数为* 1+P(i-1,K-1)。* 2)没碎。那么可以知道,没有必要去试第i层以下的楼层,接下来的问题就变成了还剩下N-i层楼,仍有K个棋子,所以总步数为* 1+P(N-i,K)。* 根据题意,在1)和2)中哪个是最差的情况,最后的取值就应该来自哪个,所以最后取值为max{P(i-1,K-1),P(N-i,K)}+1。那么* i可以选择哪些值呢?从1到N都可以选择,这就是说,第1个棋子丢在哪里呢?从第1层到第N层都可以试试,那么在这么多尝试中,我* 们应该选择哪个尝试呢?应该选择最终步数最少的那种情况。所以,P(N,K)=min{max{P(i-1,K-1),P(N-i,K)}(1<=i<=N)}+1。* 具体请参看如下代码中的solution1方法。* 方法一为暴力递归的方法,如果楼数为N,将尝试N种可能。在下一步的递归中,楼数最多为N-1,将尝试N-1种可能,所以时间复杂度* 为O(N!),这个时间复杂度非常高。** 方法二,动态规划方法。通过研究如上递归函数我们发现,P(N,K)过程依赖P(O..N-1,K-1)和P(0..N-1,K)。所以,若把所有递归* 过程的返回值看作是一个二维数组,可以用动态规划的方式优化整个递归过程,从而减少递归重复计算,如下所示:* dp[0][K]=0,dp[N][1]=N,dp[N][K]=min{max{dp[i-1][K-1],dp[N-i][K]}(1<=i<=N}+1。* 动态规划的具体过程参看如下代码中的solution2方法。* 求每个位置(a,b)(即P(a,b))的过程中,需要枚举P(0..a-1,b)和P(0..a-1,b-1),所以每个位置枚举过程的时间复杂度为O(N)。* 递归过程,即P(i,j),i从0到N,j从0到K,所以用一张NxK的二维表可以表示所有递归过程的返回值,即一共有O(NxK)个位置。所* 以方法二整体的时间复杂度为O(N^2xK)。** 方法三,把方法二的额外空间复杂度从使用NxK的矩阵,减少为2个长度为N的数组。分析动态规划的过程我们发现,dp[N][K]只需要* 它左边的数据dp[0..N-1][K-1],和它上面一排的数据dp[0..N-1][K]。那么在动态规划计算时,就可以用两个数组不停地复用的* 方式实现,而并不真的需要申请整个二维数组的空间。具体请参看如下代码中的solution3方法。** 方法二和方法三的时间复杂度为O(N^2xK),还是很高。但我们注意到,求解动态规划表中的值时,有枚举过程,此时往往可以用"四边* 形不等式"及其相关猜想来进行优化。优化的方式-四边形不等式及其相关猜想:* 1.如果已经求出了k+1个棋子在解决n层楼时的最少步骤(dp[n][k+1]),那么如果在这个尝试的过程中发现,第1个棋子扔在m层楼的* 这种尝试最终导致了最优解。则在求k个棋子在解決n层楼时(dp[n][k]),第1个棋子不需要去尝试m层以上的楼。* 举一个例子,3个棋子在解决100层楼时,第1个棋子扔在37层楼时最终导致了最优解。那么2个棋子在解决100层楼时,第1个棋子不需* 要去试37层楼以上的楼层。* 2.如果已经求出了k个棋子在解决n层楼时的最少步骤(dp[n][k]),那么如果在这个尝试的过程中发现,第1个棋子扔在m层楼的这种* 尝试最终导致了最优解。则在求k个棋子在解决n+1层楼时(dp[n+1][k]),不需要去尝试m层以下的楼。* 举一个例子,2个棋子在解决10层楼时,第1个棋子扔在4层楼时最终导致了最优解。那么2个棋子在解决11层楼或更多的层楼时(想象一* 下100层),第1个棋子也不需要去试1、2、3层楼,只用从4层及其以上的楼层试起。* 也就是说,动态规划表中的两个参数分别为棋子数和楼数,楼数变多之后,第1个棋子的尝试楼层的下限是可以确定的。棋子数变少之* 后,第1个棋子的尝试楼层的上限也是可以确定的。这样就省去了很多无效的枚举过程。证明略。注:"四边形不等式"的相关内容及其* 证明是相当复杂而烦琐的,本文由于篇幅所限,不再进行进一步的展开,有兴趣的读者可以搜集相关资料进行深入学习。本文是想用本* 题给面试者提一个醒,如果在面试时发现某一道面试题解法是动态规划,但在计算动态规划二维表的过程中,发现计算每一个值时有类* 似本题和本博客的"画匠问题"、"邮局选址问题"这样的枚举过程,则往往可以通过"四边形不等式"的优化把时间复杂度降一个维度,* 可以从O(N^2xk)或O(N^3)降到O(N^2)。具体过程请参看如下代码中的solution4方法。** @author Created by LiveEveryDay*/public class ThrowChessPieceProblem4 {public static int solution4(int nLevel, int kChess) {if (nLevel < 1 || kChess < 1) {return 0;}if (kChess == 1) {return nLevel;}int[][] dp = new int[nLevel + 1][kChess + 1];for (int i = 1; i != dp.length; i++) {dp[i][1] = i;}int[] cands = new int[kChess + 1];for (int i = 1; i != dp[0].length; i++) {dp[1][i] = 1;cands[i] = 1;}for (int i = 2; i < nLevel + 1; i++) {for (int j = kChess; j > 1; j--) {int min = Integer.MAX_VALUE;int minEnum = cands[j];int maxEnum = j == kChess ? i / 2 + 1 : cands[j + 1];for (int k = minEnum; k < maxEnum + 1; k++) {int cur = Math.max(dp[k - 1][j - 1], dp[i - k][j]);if (cur <= min) {min = cur;cands[j] = k;}}dp[i][j] = min + 1;}}return dp[nLevel][kChess];}public static void main(String[] args) {System.out.printf("The result is: %d", solution4(3, 2));}}// ------ Output ------
/*
The result is: 2
*/

【困难】丟棋子问题-Java:解法四相关推荐

  1. Think in Java第四版 读书笔记10 第16章 数组

    Think in Java第四版 读书笔记10 第16章 数组 数组和容器很像 但他们有一些差别 16.1 数组为什么特殊 数组与容器的区别主要在效率和存储类型 效率:数组是简单的线性序列 使得数组的 ...

  2. Java中四种XML解析技术之不完全测试

    Java中四种XML解析技术之不完全测试 <script language=javascript src=""></script> 在平时工作中,难免会遇到 ...

  3. 【蓝桥杯VIP】试题 历届试题 带分数(满分 Python解法+Java解法)

    [蓝桥杯VIP]试题 历届试题 带分数(满分 Python解法+Java解法) 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 100 可以表示为带分数的形式:100 = 3 + 6 ...

  4. 将1,2,…,9 共 9 个数分成 3 组,分别组成 3 个三位数,且使这 3 个三位数构成 1 : 2 : 3 的比例,试求出所有满足条件的 3个三位数---Java解法

    洛谷三连击---Java解法 题目:将1,2,-,9 共 9 个数分成 3 组,分别组成 3 个三位数,且使这 3 个三位数构成 1 : 2 : 3 的比例,试求出所有满足条件的 3个三位数. 这一题 ...

  5. 你知道Java的四种引用类型吗?

    点击蓝字 关注我们 点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 01 概述 在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用. ...

  6. LeetCode 1195. Fizz Buzz Multithreaded--并发系列题目--Java 解法--AtomicInteger/CountDownLatch/CyclicBarrier

    题目地址:Fizz Buzz Multithreaded - LeetCode Write a program that outputs the string representation of nu ...

  7. LeetCode1117. Building H2O --Java解法--多线程保证执行顺序--AtomicInteger

    此文首发于我的个人博客:LeetCode 1117. Building H2O --Java解法–多线程保证执行顺序–AtomicInteger - zhang0peter的个人博客 LeetCode ...

  8. LeetCode 1115. Print FooBar Alternately--多线程并发问题--Java解法--CyclicBarrier, synchronized, Semaphore 信号量

    此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解专栏:LeetCode题解 LeetCode 所有题目总结:LeetCode 所有题目总结 题目地址:Print FooB ...

  9. LeetCode 85. Maximal Rectangle --python,java解法

    题目地址: Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1 ...

最新文章

  1. 张亚勤、韦乐平等综述论文:通信人工智能的下一个十年
  2. timestamp 字段
  3. void main()是错误的
  4. 论文浅尝 | 面向自动分类归纳的端到端强化学习
  5. 监控管理平台 OpenNMS
  6. Visual Studio 2017 linux C++
  7. QT Creator 创建qrc文件和使用资源文件
  8. 关于数据结构(c语言)中结构体声明的LNode, *LinkList
  9. 超全面整理fastAPI(从入门到运用),进来看十秒钟再走不迟
  10. IDEA for Mac设置JVM运行参数解决运行卡顿问题
  11. 动力下肢矫形器和外骨骼辅助策略综述
  12. css sprites将多张图片合并成一张
  13. 服务器网页篡改,网站服务器网页防篡改系统
  14. Centos7上配置安装Squid代理(主动代理,与透明代理)
  15. Android硬件通信之 蓝牙通信
  16. 天使投资和风险投资有何区别?
  17. golang ODBC 访问access数据库
  18. python 决策模型_【Spark MLlib速成宝典】模型篇05决策树【Decision Tree】(Python版)...
  19. 电影的堕落? 社会的堕落?
  20. preg_match和preg_match_all的区别

热门文章

  1. SX12XXDriver-v.2.1.0 官网驱动及资料下载(免费)
  2. 微众税银受邀出席2019中国城市信用建设高峰论坛
  3. cesium1.102和以上的版本,自定义材质报‘texture2D‘ : no matching overloaded function found错误
  4. java对图片的转码和解码 实用
  5. IDEA 的空的包名默认被折叠,已解决
  6. 《犀利仁师:比武招亲》------挑战奕奕输入法开发
  7. Python 一键吸猫!找出磁盘里所有猫照
  8. IPC之Messenger传递数据
  9. 数据中心机房常见的冷却方式
  10. DSP 2803x IIC/I2C总线