分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程
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!),这个时间复杂度非常高。
*
* @author Created by LiveEveryDay
*/
public class ThrowChessPieceProblem1 {
public static int solution1(int nLevel, int kChess) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
return process1(nLevel, kChess);
}
private static int process1(int nLevel, int kChess) {
if (nLevel == 0) {
return 0;
}
if (kChess == 1) {
return nLevel;
}
int min = Integer.MAX_VALUE;
for (int i = 1; i != nLevel + 1; i++) {
if (i == nLevel) {
}
min = Math.min(min, Math.max(process1(i - 1, kChess - 1),
process1(nLevel - i, kChess)));
}
return min + 1;
}
public static void main(String[] args) {
System.out.printf("The result is: %d", solution1(3, 2));
}
}
// ------ Output ------
/*
The result is: 2
*/