【困难】丟棋子问题-Java:解法一

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

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
*/
内容概要:本文详细探讨了制造业工厂中两条交叉轨道(红色和紫色)上的自动导引车(AGV)调度问题。系统包含2辆红色轨道AGV和1辆紫色轨道AGV,它们需完成100个运输任务。文章首先介绍了AGV系统的背景和目标,即最小化所有任务的完成时间,同时考虑轨道方向性、冲突避免、安全间隔等约束条件。随后,文章展示了Python代码实现,涵盖了轨道网络建模、AGV初始化、任务调度核心逻辑、电池管理和模拟运行等多个方面。为了优化调度效果,文中还提出了冲突避免机制增强、精确轨道建模、充电策略优化以及综合调度算法等改进措施。最后,文章通过可视化与结果分析,进步验证了调度系统的有效性和可行性。 适合人群:具备定编程基础和对自动化物流系统感兴趣的工程师、研究人员及学生。 使用场景及目标:①适用于制造业工厂中多AGV调度系统的开发与优化;②帮助理解和实现复杂的AGV调度算法,提高任务完成效率和系统可靠性;③通过代码实例学习如何构建和优化AGV调度模型,掌握冲突避免、路径规划和电池管理等关键技术。 其他说明:此资源不仅提供了详细的代码实现和理论分析,还包括了可视化工具和性能评估方法,使读者能够在实践中更好地理解和应用AGV调度技术。此外,文章还强调了任务特征分析的重要性,并提出了基于任务特征的动态调度策略,以应对高峰时段和卸载站拥堵等情况。
内容概要:本文介绍了个使用MATLAB编写的基于FDTD(时域有限差分)方法的电磁波在自由空间中传播的仿真系统。该系统采用了ABC(吸收边界条件)和正弦脉冲激励源,并附有详细的代码注释。文中首先介绍了关键参数的选择依据及其重要性,如空间步长(dx)和时间步长(dt),并解释了它们对算法稳定性和精度的影响。接着阐述了电场和磁场的初始化以及Yee网格的布局方式,强调了电场和磁场分量在网格中的交错排列。然后详细讲解了吸收边界的实现方法,指出其简单而有效的特性,并提醒了调整衰减系数时需要注意的问题。最后,描述了正弦脉冲激励源的设计思路,包括脉冲中心时间和宽度的选择,以及如何将高斯包络与正弦振荡相结合以确保频带集中。此外,还展示了时间步进循环的具体步骤,说明了磁场和电场分量的更新顺序及其背后的物理意义。 适合人群:对电磁波传播模拟感兴趣的科研人员、高校学生及工程技术人员,尤其是那些希望深入了解FDTD方法及其具体实现的人群。 使用场景及目标:适用于教学演示、学术研究和技术开发等领域,旨在帮助使用者掌握FDTD方法的基本原理和实际应用,为后续深入研究打下坚实基础。 阅读建议:由于本文涉及较多的专业术语和技术细节,建议读者提前熟悉相关背景知识,如电磁理论、MATLAB编程等。同时,可以通过动手实践代码来加深理解和记忆。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值