三道题理解动态规划
来源:互联网 发布:mysql top用法 编辑:程序博客网 时间:2024/05/04 20:45
动态规划是算法导论中介绍的最重要的几种基本算法之一,因为好长时间没有看书,再加上原来就理解的不深入,所以早就忘的差不多了,这两天正好因为一道面试题复习一下。
用几句话描述动态规划问题如下:
一个问题可以分解若干子问题,每一个子问题为一种状态,求出每一个状态的最优解,进而在它的帮助下求出下一个状态的最优解。
解决动态规划问题,最重要的步骤就是找出状态转移方程。有了状态转移方程就可以根据初始状态(边界)求出每一个状态的最优解。
动归问题的特点如下:
最优子结构
子问题重叠
边界
子问题独立
下面用三道题目帮组理解一下。
用最少的硬币得到给定的money
有1分,3分,5分3种硬币,如何使用最少的硬币数量得到12分。这个题目的状态转移方程如下。
d(i) = min(d(i-v(j)) + 1)
其中d是硬币数量,i是money总数,v(j)是第j个硬币的单位。初始值d(0)=0。代码如下:
#! /usr/bin/env python # -*- coding:gbk -*- class Solution(object): def get_min_count(self, money, item_list): num_list = {} if money == 0: return 0 num_list[0] = 0 for i in range(1, money + 1): min = (1<<31) - 1 index = -1 for j in range(0, len(item_list)): if item_list[j] <= i: if min > num_list[i - item_list[j]] + 1: min = num_list[i - item_list[j]] + 1 index = j print "cur_index:%d cur_item:%d pre_index:%d pre_num:%d" \\ %(i, item_list[index], i - item_list[index], num_list[i - item_list[index]]) num_list[i] = min return num_list[money] if __name__ == "__main__": s = Solution() money = 12 item_list = [1, 3, 5] print s.get_min_count(money, item_list)
最长升序子数列
题目的意思就是从一个数列当中找出最长的升序的子数列,比如”123412345123”的最长升序子数列是”12345”,这个题目的状态转移方程如下。
d(i) = d(i)+1 [if a[i] > a[j] i > j] or d(i) = 1 [if a[i] < a[j] i > j]
其中d是长度,i和j分别代表第i和j个字符,初始值d(0)=0。代码如下:
#! /usr/bin/env python # -*- coding:gbk -*- class Solution(object): def max_up_seq(self, seq): if len(seq) == 0: return 0 ret_len = {} ret_len[0] = 1 max_len = 1 max_seq_start = 0 for i in range(0, len(seq) - 1): if seq[i + 1] >= seq[i]: ret_len[i+1] = ret_len[i] + 1 else: ret_len[i+1] = 1 if max_len < ret_len[i]: max_len = ret_len[i] max_seq_start = i - max_len + 1 if max_len < ret_len[len(seq) - 1]: max_len = ret_len[len(seq) - 1] max_seq_start = len(seq) - max_len return seq[max_seq_start:max_seq_start + max_len] if __name__ == "__main__": s = Solution() print s.max_up_seq([1,2,3,4]) print s.max_up_seq([1,2,3,4,2,3,3,4]) print s.max_up_seq([1,2,1,2,3,4,7,8,9,1,2,4,5,7])
0-1背包问题
这道题是动态规划最经典的问题,网上求解方法很多。题目内容大致是, 有5个商品,背包的体积为10,他们的体积为 c[5] = {2, 2, 6, 5, 4}, 价值为 v[5] = {6, 3, 5, 4, 6},如何利用背包的体积放入价值最大的物品。一个物品只能放入或者没有放入背包。
状态方程如下。
V[i][j]=max(V[i-1][j],f[i-1][j-ci]+vi)
其中C是背包体积,V[i][j]放入第i个物品总体积为j时的总价值,c[i]是第i个商品体积,v[i]是第i商品价值。代码如下:
# include <cstdio> const int MAX_NUM = 100; int V[MAX_NUM][MAX_NUM]; int bag(int volum, int n, int* weight, int* value) { if (volum == 0) { return 0; } for (int i = 0; i < n + 1; ++i) { V[i][0] = 0; // printf("weight:%d value:%d\", weight[i], value[i]); } for (int i = 0; i < volum + 1; ++i) { V[0][i] = 0; } printf("volum:%d num:%d\", volum, n); for (int j = 1; j < volum+1; ++j) { for (int i = 1; i < n+1; ++i) { int max = V[i -1][j]; // printf("max:%d ", max); if (j < weight[i]) { // printf("j<weight[i] "); V[i][j] = V[i - 1][j]; } else { // printf("j>=weight[i] "); if (max < V[i - 1][j - weight[i]] + value[i]) { max = V[i - 1][j - weight[i]] + value[i]; } V[i][j] = max; } printf("%d %d item:%d\", i, j, V[i][j]); } } return 0; } int main() { int weight[6] = {0, 2, 2, 6, 5, 4}; int value[6] = {0, 6, 3, 5, 4, 6}; bag(10, 5, weight, value); printf("max value: %d\", V[5][10]); return 0; }
- 三道题理解动态规划
- 动态规划理解
- 理解动态规划
- 动态规划理解
- 动态规划~概念理解
- 深入浅出理解动态规划
- 理解动态规划
- 深入理解动态规划
- 动态规划简单理解
- 动态规划--总体理解
- 动态规划理解
- 动态规划理解
- 动态规划理解
- 动态规划的理解
- 动态规划的一点理解
- 动态规划算法的理解
- 关于动态规划的理解
- 深入理解动态规划DP
- 【linux】【kernel】【gpio】imx-m6-vab820与ZX2000上的GPIO sysfs
- 提升iOS审核通过率之“IPv6兼容测试”
- LeetCode:String to Integer (atoi)
- 单页WEB应用(四),Model数据模型模块
- Altium Designer拖动器件消失的解决办法
- 三道题理解动态规划
- LintCode 13 字符串查找
- Redis Cluster集群配置
- [BZOJ2729][HNOI2012]排队(组合数学+高精度)
- 11g RAC 如何备份OCR,利用备份恢复OCR,ocrdump
- 整数四则运算的java实现-栈和队列的使用练习
- Android简单计算器界面实现
- 建站参考资料
- Protobuf反射机制设置元素