回 帖 发 新 帖 刷新版面

主题:计算楼层的一个算法题,很费脑筋啊~~

一百层的大楼,你有两个相同的玻璃棋子,从某层扔下就会碎,用这俩棋子找出一个最优策略,并求此策所需扔的最大次数,来得知那个临界层面。


各位想想?
想到之后,再想想,如果棋子有3个,那最优策略是啥呢?

回复列表 (共9个回复)

沙发

如果要保持扔的最大次数为一个常数a1,那么第一颗子第1次在a1楼扔若不碎,第i次应该在ai=i*a1-i*(i-1)/2楼扔,如果碎了,那么第二颗子应该从第一颗最后一次不碎的上一层楼一楼一楼的往上扔。至于a1,n与100的关系,似乎要通过求极值来计算了。大家伙一块想。
3个棋子的情况还没来得及想。

板凳

哎呀,我笨了,a1就是n次,那么根据递推式
an=n*a1-n*(n-1)/2=n*n/2+n/2<=100
解出n=13.65,取整n=14。那么,此题目扔的最大次数为14次。


补充说明,递推公式的由来
ai=i*a1-i*(i-1)/2

a1          (a1是第1次扔的楼层,次数最多为a1)
a2+1-a1=a1  (a2是第2次扔的楼层,+1表示a1扔的这一次,-a1表示起始楼层在a1+1层,
             =a1是扔的次数最多为a1)
同理
a[i]+i-1-a[i-1]=a1,(为不至于混淆ai-1和a(i-1),特加上方括号)
化简得上面的递推公式

举例说明
假如a1=4,如果碎了,那么第2颗棋子在1,2,3楼扔,最多4次
如果没碎,a2=7,碎了,第2颗棋子在5,6楼扔,加上第一颗扔的2次,最多4次。

3个棋子的还是没想呢,慢慢[em18]

3 楼

100=10*10  
100=4*5*5

4 楼

原来有讨论过的,n个棋子的情况都可以算,就是DP

5 楼

好象是一个游戏公司的面试题...
不过人家是扔2台PS...

6 楼

扔PS啊,测PS的抗摔能力

7 楼

[quote]哎呀,我笨了,a1就是n次,那么根据递推式
an=n*a1-n*(n-1)/2=n*n/2+n/2<=100
解出n=13.65,取整n=14。那么,此题目扔的最大次数为14次。


补充说明,递推公式的由来
ai=i*a1-i*(i-1)/2

a1          (a1是第1次扔的楼层,次数最多为a1)
a2+1-a1=a1  (a2是第2次扔的楼层,+1表示a1扔的这一次,-a1表示起始楼层在a1+1层,
             =a1是扔的次数最多为a1)
同理
a[i]+i-1-a[i-1]=a1,(为不至于混淆ai-1和a(i-1),特加上方括号)
化简得上面的递推公式

举例说明
假如a1=4,如果碎了,那么第2颗棋子在1,2,3楼扔,最多4次
如果没碎,a2=7,碎了,第2颗棋子在5,6楼扔,加上第一颗扔的2次,最多4次。

3个棋子的还是没想呢,慢慢[em18][/quote]
【n是实验次数,k是楼层数】
1棋子  1  2  3  4  5   ... n <= k 【k为100,则n为100】  
2棋子  1  3  6  10 15  ...   n(n+1)/2 <= k 【k为100,则n为14】
3棋子  1  4  10 20 35  ...   n(n+1)(n+2)/6 <= k 【k为100,则n为8】
4棋子  1  5  15 35 70  ...  n(n+1)(n+2)(n+3)/24 <= k 【k为100,则n为6】
i棋子  1 i+1 ...          n(n+1)...(n+i-1)/i! <= k

8 楼

上面的分析好像不对劲,如果棋子数足够多的话,就可以使用二分法,此时应该是log2(k) = log2(100) ,即对于100层楼应该是7才对。这样的话,4个棋子得出的6次就不对了。对于4个棋子究竟应该是几次呢?

9 楼

写了个程序,果然7楼的分析到4个子时已经错了。对于100层来说,不管棋子多说,最少的步数就是7(即二分法的数目)
int floor(int floors, int chess)
{
    int        count[10001][2];
    int        i, j, k;
    int        bottom, top;

    for(i=0; i<=floors; ++i)
    {
        count[i][0] = i;
    }
    count[0][1] = 0;
    count[1][1] = 1;
    count[2][1] = 2;


    top = 1;
    bottom = 0;
    for(i=1; i<chess; ++i)
    {
        for(j=3; j<=floors; ++j)
        {
            int        min = 65535, max;
            for(k=0; k<j; ++k)
            {
                if(count[k][bottom]+1 < count[j-k-1][top]+1)
                    max = count[j-k-1][top]+1;
                else
                    max = count[k][bottom]+1;
                if(min > max)
                {
                    min = max;
                }
            }
            count[j][top] = min;
        }

        int        temp;
        temp = bottom;
        bottom = top;
        top = temp;
    }

    return count[floors][bottom];
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册