丢棋子问题

本文探讨了一种优化算法,用于解决在有限的棋子数量下,如何以最少的尝试次数确定一座大楼中棋子不会摔碎的最高楼层。问题涉及到递归与动态规划,给出了暴力解法的时间复杂度为O(N!),并提出了一种更优的解决方案,通过构建部分状态转移表来减少尝试次数。在给定的例子中,如N=105, K=2时,最优解只需要14次尝试。
摘要由CSDN通过智能技术生成

丢棋子问题

原文链接:https://www.cnblogs.com/willwuss/p/12256475.html

题目描述

一座大楼一共有0~N层,地面算第0层,最高一层为第N层。已知棋子从第0层掉落肯定不会摔碎,从第i层掉落可能回摔碎,也可能不会摔碎(1<=i<=N)。给定整数N作为楼层数,再给定整数K作为棋子数,返回如果想找到棋子不会摔碎的最高层数,即使在最差的情况下仍的最少次数。一次只能仍一个棋子。

例子
N=10, K=1.
返回10。因为只有1颗棋子,所以不得不从第一层开始一直试到第十层,最差情况要扔10次。

N=3, K=2.
返回2。现在第2层仍1颗棋子,如果碎了,试第1层;如果没碎,试第3层。

N=105, K=2.
返回14。
在这里插入图片描述

暴力解法

在这里插入图片描述

** Solution one **
** 时间复杂度 O(N!) **
    public int solutionOne(int N, int K){
        if ( N<1 || K<1 ) 
            return 0;
        return helper1(N, K);       
    }
    private int helper1(int N, int K){
        if ( N==0 ) return 0;
        if ( K==1 ) return N;

        int min = Integer.MAX_VALUE;
        for(int i=1; i<=N; ++i){
            min = Math.min(min, Math.max( helper1(i-1, K-1), helper1(N-i, K)));
        }
        return min+1;
    }

最优解

在这里插入图片描述
代码实现Map建立部分,对应上图的表应该把头左斜着90°看

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回最差情况下扔棋子的最小次数
     * @param n int整型 楼层数
     * @param k int整型 棋子数
     * @return int整型
     */
    public int solve (int n, int k) {
        // write code here
        if(n < 1 || k < 1) return 0;
        //另外还有一个特别重要的优化,我们知道N层楼完全用二分的方式扔logN+1次就直接可以确定哪层楼是会碎的最低层楼
        
        int times = (int)(Math.log(n)/Math.log(2)) + 1;
        if(k >= times) return times;
        
        int[] dp = new int[k];
        int res = 0;
        //构建几个棋子可以扔多少次就能最大判断的楼数Map表,
        //map[i][j] == map[i-1][j] + map[i-1][j-1] + 1
        while(true){
            res ++;
            int pre = 0;
            for(int i=0; i<k; i++){
                int temp = dp[i];
                dp[i] = dp[i] + pre + 1;
                pre = temp;
                if(dp[i] >= n) return res;
            }
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值