递归、加法原理,如何分解问题(独立且完备的划分)
2015-10-10 23:54
393 查看
加法原理适用于做一件事有n种独立不相交且完备的方向,每个方向上有ai种方案,则总的方案数就是 a1 + a2 +... + an
例题:把n个数分为k个非空子集,有多少种分法?
分解问题:第一个集合里放多少个数把原问题的解分成了独立且完备的若干方向,分别解每个方向上的方案数,然后相加
还有一种形式的加法原理,适用于最优解问题,还是原问题划分为若干独立且完备的方向,每个方向上的最优解中取最优的。比如背包问题,第一个物品取或不取就是这样一种独立且完备的划分,全局最优解就是这两种情况下的最优解中最优的那个
分组问题:n个数分成k组,打印所有的方案
如何划分问题:当前数数分到哪个组作为划分,然后递归问题。注意剪枝去重和排除空集。去重:尽量往前堆
分组问题的应用POJ1011:给定一组小棍子的长度,拼接一组等长的大棍子,求最小的等长长度。
分析:枚举可能的长度,最小为小棍子中最长的那根,最大为所有棍子拼成一根大棍子的长度,这个长度值还必须能被总长度整除(只考虑整数长度)
对于每个可能的长度len,尝试对小棍子进行分组,条件是组长度不能超过len,如果最后能分完,每个组的长度都 <= len, 则其实都是==len,否则如果有小于len的必然就有>大于len的。
例题:把n个数分为k个非空子集,有多少种分法?
分解问题:第一个集合里放多少个数把原问题的解分成了独立且完备的若干方向,分别解每个方向上的方案数,然后相加
memo = [[-1] * (1000) for i in xrange(1001)] def group(n, k): if k == 0: return 1 if n == 0 else 0 if memo [k] > 0: return memo [k] ans = 0 for i in xrange(1, n - (k - 1) + 1): ans += group(n - i, k - 1) * C(n, i) memo [k] = ans return ans
还有一种形式的加法原理,适用于最优解问题,还是原问题划分为若干独立且完备的方向,每个方向上的最优解中取最优的。比如背包问题,第一个物品取或不取就是这样一种独立且完备的划分,全局最优解就是这两种情况下的最优解中最优的那个
def backpack(V, W, C, i): if i == len(V) or C == 0: return 0 ans = backpack(V, W, C, i + 1) if W[i] <= C: ans = min (ans, backpack(V, W, C - W[i], i + 1)); return ans;
分组问题:n个数分成k组,打印所有的方案
如何划分问题:当前数数分到哪个组作为划分,然后递归问题。注意剪枝去重和排除空集。去重:尽量往前堆
def group(A, k): groups = [[] for i in xrange(k)] def dfs(i, allocated): if i == len(A) and allocated == k: print groups elif k - allocated <= len(A) - i: for j in xrange(k): groups[j].append(A[i]) dfs(i + 1, allocated + 1 if len(groups[j]) == 1 else allocated) groups[j].pop() if len(groups[j]) == 0: break dfs(0, 0)
分组问题的应用POJ1011:给定一组小棍子的长度,拼接一组等长的大棍子,求最小的等长长度。
分析:枚举可能的长度,最小为小棍子中最长的那根,最大为所有棍子拼成一根大棍子的长度,这个长度值还必须能被总长度整除(只考虑整数长度)
对于每个可能的长度len,尝试对小棍子进行分组,条件是组长度不能超过len,如果最后能分完,每个组的长度都 <= len, 则其实都是==len,否则如果有小于len的必然就有>大于len的。
def minEqualtick(A): minLen, total, lower = [sum(A)], sum(A), max(A) for l in xrange(lower, total): if total % l != 0: continue k, groups = total / l, [0] * (total / l) def group(i): if i == len(A): minLen[0] = l else: for j in xrange(0, k): if groups[j] <= l - A[i]: groups[j] += A[i] group(i + 1) groups[j] -= A[i] if groups[j] == 0: break group(0) return minLen[0], total / minLen[0], total
相关文章推荐
- 8086汇编笔记(0)
- xcode4中build Settings常见参数解析
- 单链表链式结构的创建
- UVA-1610 Party Games (构造)
- 中国剩余定理 /孙子定理
- 苹果开发 笔记(80)升级IOS 9 和 XCode 7 引起的问题记录
- DSP/BIOS入门
- 5499 SDOI
- 在Android Studio里导入library(以github里的SlidingMenu为例),jar包及so的步骤
- UVa 439 Knight Moves
- Java Lambda表达式
- Raycasting光线投射
- 【10.04】【整理收集】那些神器级别的BT磁力搜索网站
- 消息循环与Looper
- Ctrl+Alt+T恢复启动Ubuntu默认终端
- COIDE2.0.2无法新建工程的解决方法
- Elasticsearch基础教程
- 空间(space)
- Linux开发中,make命令的使用
- ORACLE同义词