Chinaunix首页 | 论坛 | 博客
  • 博客访问: 347957
  • 博文数量: 105
  • 博客积分: 2730
  • 博客等级: 少校
  • 技术积分: 1110
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-20 12:09
文章分类

全部博文(105)

文章存档

2013年(3)

2012年(2)

2011年(36)

2010年(34)

2009年(6)

2008年(20)

2007年(4)

分类:

2011-03-29 18:52:29

问题描述, m个筐的(集合表示M),n个苹果,1<=m<=n.
在每个筐中都至少放一个苹果,则筐i中有m(i)个苹果 (1<=i<=m, mi >=1, sum(m(i)) == n).
对于任意给出的k, 1<=k<=n, 都满足能找到一个M的子集, 这些筐中的苹果总数正好是k.
  i' 是 M'中对应M的坐标, M'属于M, 满足sum(m(i')) == k
要求:给出给定(m,n)对应的所有解.

放的结果是一组数字,不用关心顺序,那么对于任意的解,都可以表示成一个[非严格递增序列].
比如5个苹果3个筐,可以的解是[1,2,2],[1,1,3]. 而[3,1,1]和[1,1,3]是等价的.所以解有2个.

从第一个筐开始放,当已经放好了k个筐时,一共放了h个苹果,第k个筐有r个苹果,并且满足子问题(k,h)
那么第k+1个筐中可选的苹果数r'必须满足
 {r' | r <= r' <= h+1, h+r' <= n}     ...................(1)
证明:
 因为前k个筐的h个苹果可以表示[1,h]区间内的数,
 而新加进来的r'和前解做加法,可以表示[1+r',h+r']范围内的数,
 加上r'本身,r'加入后能够表示的区间是([1,h] 并 [r',h+r']). 要保证这一区间连续才能是有效解.
 所以选择r'<=h+1.
 又因为需要是递增序列,所以r'要不小于r, 并且还要有足够的苹果可供使用.
这样递归地求解子问题就可以得出所有的组合了.

启动:为了表示1,第一步可以直接放入一个苹果,或者在第0个筐中放入0个苹果也能满足递归要求,0号筐并不存在.
递归解:如果进行到最后一步,所剩的苹果如果满足(1)的条件,那么返回唯一解,如果不满足,则返回空解.
如果子问题返回空解,则对应的选择无可行解,返回空解.
剪枝:在(1)的情况下,如果还剩x个苹果和y个筐,
 判断: y * r <= x <= (h+1) * (2^y -1), 如果为假,则停止递归,返回空解.
证明:
 按照递增要求,如果k筐有r个苹果,则剩下的每个框都至少有r个苹果
 按照(1)中的区间要求k+1筐中最多有h+1个苹果,k+2中最多有(h+(h+1)) + 1个苹果就是2*(h+1),
   依次每个框中最多的苹果翻倍,求和得到后面可放苹果的上界,也就是判断的右半部分.



阅读(713) | 评论(0) | 转发(0) |
0

上一篇:KMP matcher in Haskell

下一篇:平凡,平凡解

给主人留下些什么吧!~~