Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4560639
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Python/Ruby

2012-05-11 12:38:32

100层楼2个鸡蛋,如何得知鸡蛋能承受几层的撞击。没太明白题意,google之。

1. 你有2个一摸一样的鸡蛋(所有性质相同)。
2. 有一幢100层的楼。注意即使是一楼和地面也有距离的。
3. 鸡蛋可能很硬也可能很软, 意思是有可能从一楼扔下来就碎了, 也有可能从100楼扔下来还不碎。
4. 你必须,是*必须*搞清楚最高从几楼扔下来鸡蛋是不会碎的。
5. 此过程中你被允许打破这2个鸡蛋。
6. 只准用从楼上扔鸡蛋的方式测试, 不能有任何别的辅助工具和手段。

微阅堂一个OI博客 都有提到过,曾经也和同学讨论过,这次看到有点蒙,想了一会想出来了。

不能用二分法,因为如果在50层碎了,下面的策略就是一层一层的试验了。一定有一个最低层L,碎了就从第一层测试到L-1层,没碎就往上走。

测试一次如果没碎,那么往上走的层数需要比上一次上楼的层数减1,上到100层时上楼的次数就应该等于L,这样无论在哪里第一个蛋碎了,两个蛋测试总次数都是相同的。

于是: L + (L-1) + ... + (L-L) = 100  =>  L*L - [1+2+...+(L-1)] = 100

解得: L = 13.x

最后验证:

14+13+12+11+10+9+8+7+6+5+4 = 99      用了11次.

13+12+11+10+9+8+7+6+5+4+3+2+1=91  不到100

结果是14。连程序都省了。


如果微阅堂的300层楼,3个鸡蛋呢?这个要用到动态规划(DP)。

有n层楼k个鸡蛋,则在第r层楼扔下鸡蛋只有破和不破两种情况,如果破了则问题转化为测定n-1层楼,k-1个鸡蛋所需的最小次数+1;如果不破则转化为测定n-r层楼,k个鸡蛋所需的最小次数。

公式表示:

F(n, k) = min ( max(F(n-r, k) , F(r-1, k-1)) + 1), r = 1, 2, …, n;
F(n, 1) = n; F(0, n) = 0

递归的程序:

点击(此处)折叠或打开

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-

  3. import sys

  4. def memo(f):
  5.     table = {}
  6.     def fmemo(*args):
  7.         if args not in table:
  8.             table[args] = f(*args)
  9.         return table[args]
  10.     fmemo.memo = table
  11.     return fmemo

  12. @memo
  13. def func(n, k):
  14.     if k == 1: return n
  15.     if n == 0: return 0
  16.     least = n
  17.     for r in range(1, n+1):
  18.         keep = func(n-r, k) + 1
  19.         broke = func(r-1, k-1) + 1
  20.         step = max(keep, broke)
  21.         if least > step:
  22.             least = step
  23.     return least

  24. if __name__ == '__main__':
  25.     ret = func(100, 2)
  26.     print(ret)
  27.     ret = func(300, 3)
  28.     print(ret)
  29.     sys.setrecursionlimit(15000)
  30.     ret = func(900, 9)

问题:

   做了cache,貌似是吧时间复杂度从指数降到O(nk)级别了。递归的时间复杂度总是想不清楚。 

   大数据量时python有递归层数限制,无法计算,可以转换成C代码。但毕竟系统栈有限(貌似2M),用递归不是最好的方法。谁有更好的方法吗?

阅读(1898) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~