动态规划-试题(1)-扔玻璃珠

8 篇文章 0 订阅
6 篇文章 0 订阅

扔玻璃珠

/**
*
* 某幢大楼有100层。
*
* 你手里有两颗一模一样的玻璃珠。当你拿着玻璃珠在某一层往下扔的时候,一定会有两个结果,
* 玻璃珠碎了或者没碎。这幢大楼有个临界楼层。低于它的楼层,往下扔玻璃珠,玻璃珠不会碎,
* 等于或高于它的楼层,扔下玻璃珠,玻璃珠一定会碎。玻璃珠碎了就不能再扔。
*
* 现在让你设计一种方式,使得在该方式下,最坏的情况扔的次数比其他任何方式最坏的次数都少。
* 也就是设计一种最有效的方式。
*/

分析

这段分析来自 http://www.cnblogs.com/grenet/archive/2009/12/20/1628425.html 作者:万仓一黍

这个问题的实质是找出临界楼层。要想使用2个玻璃珠来找到结果,有2类方法。
1、 使用一个玻璃珠从1楼开始一直往上找,第一次玻璃珠碎掉的楼层就是临界楼层。假定为N,那么我们要扔N次。
2、第一次选择在60层扔,若碎了,说明临界点在60层及以下楼层,这时只有一颗珠子,剩下的只能是从第一层,一层一层往上实验,最坏的情况,要实验59次,加上之前的第一次,一共60次。若没碎,则只要从61层往上试即可,最多只要试40次,加上之前一共需41次。两种情况取最多的那种。故这种方式最坏的情况要试60次。

那该如何设计方式呢?
仔细分析一下,关键是第一次的选择,假设在第N层,如果第一次扔的时候就碎了,那么第二颗珠子只能是从第1层开始一层层往上试,此时,最坏的情况为N-1次,加上第一次,则一共为N层。那如果不碎呢,第二颗珠子会从N+1层开始试吗?很显然不会,此时大楼还剩100-N层,问题就转化为100-N,2颗珠子,请设计最有效方式。

定义一个函数F(N),表示N层楼最有效方式最坏情况的次数。
通过上面的分析,有

F(N)=Min(Max(1,1+F(N-1)),Max(2,1+F(N-2)),……,Max(N-1,1+F(1)))
F(1)=1
本面试题就是求F(100)

代码

    /**
     * 所有的数组的第一位,也就是int[0]是无效的,int[1]表示一楼或者第一次。
     * @param args
     */
    public static void main(String[] args){

        int N = 100;//楼层总数

        int dp[] = new int[N+1];//用于保存第N楼的最佳次数
        dp[1] = 1;//一楼只需要1次

        int pos[] = new int[N+1];//pos[10]表示,10层大楼扔玻璃珠的位置
        pos[1] = 1;//只有1层楼只能在1楼扔

        //从2层大楼开始
        for (int i = 2; i <= N; i++) {

            int min = N;//每层大楼的最坏情况的最少次数

            for (int j = 1; j < i; j++) {
                int max = dp[i-j] + 1;
                if (max < j)
                    max = j;
                if (min > max) {
                    min = max;
                    pos[i] = j;//记录投掷楼层
                }
            }
            dp[i] = min;
        }

        System.out.println(dp[N]);


        /*找出每次投掷的楼层*/

        int total = N;//每一次的楼层总数
        int[] cast = new int[dp[N]+1];//每一次投掷的位置

        for (int i = 1; i <= dp[N]; i++) {
           cast[i] = pos[total];
           total -= cast[i];
        }

        for (int i = 1; i <= dp[N]; i++) {
            cast[i] += cast[i-1];
        }


        /*打印结果*/
        for (int i : cast) {
            System.out.print(i + " ");
        }


    }

运行结果

14
0 9 22 34 45 55 64 72 79 85 90 94 97 99 100

为什么会出现0呢,别忘了int[0]是无效的。所以真正的每次扔玻璃珠的楼层是
9 22 34 45 55 64 72 79 85 90 94 97 99 100

感谢

http://www.cnblogs.com/grenet/archive/2009/12/20/1628425.html 的分析

http://t.cn/RK12kzL Dan2的回答

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值