其实我一直在想一个问题,为什么我觉得学习计算机算法比高中的数学难?
记得高中的数学那是信手撵来(当然不是每一道题目),不谈学得有多好,但是起码对待每一道数学题都有自己的思路,想法,一般都能解出来,但是为什么学习计算机算法的时候就没有这种感觉呢。宏观上看过去第一眼肯定是计算机算法一般都是文字性表述,应该比高中的数学逻辑简单吧。但是,为什么学习计算机算法就感觉特别不自然。对于简单的题目套用简单的解法思路都好难实现出来,难道是我的脑袋退化了?
不过,客观上讲,大学课程,当然要比高中课程层次要高。
由于我看的是算法导论,所以讲的比较清楚(PS:翻译不说有多好,但是肯定会有晦涩的地方),关于高级的计算机算法设计中分为3类问题(按照书上划分的):动态规划,贪心算法,平摊分析。其实,计算机算法也有运筹学的内容,有关效率选择,最大价值等等。我能想到的应用就是什么主从节点的选择,考虑到最少的成本而获得最大计算机利用率之类的。我自然时根据书中的规划来学习的,首先接触的是动态规划。
在现实问题中,人们对于这样一类问题:在进行解的选择时,下一步的选择会影响到前面的选择而导致整个前面选择的解发生变化,这样,人们的脑袋可是想象不过来,递归的进行重新选择解(如果人的脑袋有很好的rom就好了);其实在没有接触贪心算法的时候,我们很擅长用这种思想解决问题,比如进行路程最短问题,我们总是会先选择我们能进行选择的路程试探,找到最短的路程,然后在进行下一步的选择,这是最简单的思想,所谓贪心算法。但是,就像我方才提到的,有些问题是不能通过“贪心”选择的,下面是一个方便的例子(书上太多例子了,不知道那一个最能说明问题):0-1背包问题;
小偷进入了一家首饰店,首饰店中每一件物品有且只有一件,共有n件,店中有太多的首饰,小偷看看他可怜的布袋,最多能装下体积为V的首饰,对于每一件首饰i,其价值为Wi,体积为Vi,所以,小偷要进行选择,选择在其布袋中能装下并且价值最大的一些首饰。(脚趾头想一想都知道,不能先选择价值最大的首饰,你们懂的~),貌似用高中排列组合的话,能取到是2的N次方种组合,而且还要考虑到体积最大问题,如果这个小偷有这种脑袋的话,他也算NB了(如果有,应该不用做小偷了),指数级的选择次数,计算机算法中它是低效的,那,我们现在来观察一下,有没有更好的办法。递归,貌似是很适合该类问题的,对于递归的解法,我们是要找到递归子,即对于每一个大问题,总有一个小问题能嵌于其中并且是递归嵌套的,0-1背包问题中,我们观察到,如果是在选择物品i时,其总价值最大并且体积不能超出,要么是在现在加入i物品后体积内除去该物品的最大价值,要么是在加入该物品后体积内包含该物品并且剩余体积内价值最大的物品组合。这是一个很难表述的解法,下面是一个函数式(其实时wiki上down的,有了它,好理解多了):
f[i][j]{
f[i-1,j] {j<Vi}
max{f[i-1,j],f[i-1,j-Vi]+Pi} {j>=Vi}
0 {i=0 OR j=0}
}
关键是中间一个式子,我们来看一个具体的例子:
体积分别为:{2,2,6,5,4}
价值分别为:{6,3,5,4,6}
现在,如果我们规定最大体积为6,我们直观看到如果我们选择第1,2件物品,体积为4,价值为9,如果我们继续添加,那么就超出了最大体积,现在,只能是在剩余的物品中替换现有的,首先考虑物品3,4,如果替换任意其中之一,那么将超出最大体积约束,再来看看物品5,体积为4,替换已有选择的物品中任意一件,不会破坏条件,那么,我们就来比较一下,如果替换了该物品,体积编程6,价值为12,大于9,但是,我们知道,现在体积变大了(原先是4),所以,我们还需要考虑在没有添加物品5之前,体积为6,并且最大价值最大的组合,貌似还是物品1,2的组合,价值为9,不大于现有价值12,那么,我们就可以成功添加该物品5。
下面是实现代码:
public class Bag_01{
static void bag_pro(int[] w,int v[],int maxWeight){
int[][] vw = new int[w.length][maxWeight+1];
for(int i=0;i<maxWeight+1;i++){
if(w[0]<=i){
vw[0][i] = v[0];
} else {
vw[0][i] = 0;
}
}
for(int i = 1;i<w.length;i++){
for(int j = 0;j<maxWeight+1;j++){
if(j<w[i]){
vw[i][j] = vw[i-1][j];
} else if(vw[i-1][j]<=(vw[i-1][j-w[i]]+v[i])){
vw[i][j] = vw[i-1][j-w[i]]+v[i];
} else {
vw[i][j] = vw[i-1][j];
}
}
}
for(int i = 0;i<w.length;i++){
for(int j = 0;j<maxWeight+1;j++){
System.out.print(vw[i][j]+" ");
}
System.out.print("\n");
}
}
public static void main(String args[]){
int w[] = {2,2,6,5,4};
int v[] = {6,3,5,4,6};
int maxWeight = 6;
bag_pro(w,v,maxWeight);
}
}
打印出来的是对每一规定最大体积内的体积逐步添加物品的最大价值的表;
上面的例子比较直观,用于动态规划的思路去解决问题,其思想就是找到一个可以递归的子问题,子问题的最优解即问题的最优解。这是我们思考问题的方式,递归使用于动态规划的寻找最优子问题结构,至于寻找子问题的解的结构,可以是迭代,也可以是递归。下面是“官方”步骤:
1.描述最优解结构;
2.递归定义最优解的值;
3.按自底向上的方式计算最优解的值;
4.由计算出的结果构造一个最优解;
当然,动态规划的最重要一点就是3,一定是自底向上求解过程,这样,才能运用到递归的子结构。通过子问题的最优解,得到问题的最优解。就像是背包问题,我们一定是求表中最后一列,最后一行的值,而该值是通过它的前列或者时前行得到的。
动态规划除了最优的子结构,还有一特征就是重叠的子问题,之所以动态规划能够缩减运行的时间,就是通过在以得到的子问题解中寻找值,而不是又一次计算,人脑之所以不能动态规划解决问题就是因为人脑没有那么一块地方保存先前计算的值,就算你记住了10个值,能记住100个?1000个?
最后,两点,重叠子问题,最优子结构,自底向上。
分享到:
相关推荐
"动态规划算法的应用" 动态规划算法是一种非常强大且广泛应用的算法思想,它可以解决许多复杂的问题。动态规划算法的核心思想是将问题分解成小问题,然后使用Memoization技术将中间结果存储起来,以便后续问题的...
动态规划算法经典题目分析 动态规划是一种非常经典的算法思想,解决的问题领域非常广泛。动态规划的基本思想是将一个复杂的问题分解成多个小问题,通过解决这些小问题来解决整个问题。今天,我们将要探讨动态规划的...
动态规划算法课件PPT 动态规划算法是解决问题的有效方法,它将问题分解成多个子问题,然后通过解决这些子问题来解决原问题。动态规划算法与分治法类似,但不同的是,动态规划算法中子问题之间存在相互依赖关系,...
动态规划算法是一种强大的工具,主要用于解决多阶段决策过程中的最优化问题。在计算机科学和算法设计中,动态规划提供了一种系统化的方法来处理复杂问题,尤其在那些问题的最优解可以通过组合子问题的最优解来得出的...
北京工业大学--算法作业2--动态规划算法实现0-1背包问题---Java代码 利用动态规划算法实现0-1背包问题或装配线调度问题。(二选一) 要求测试数据以文本文件的形式存储, 即所有的数据由文本文件读入。 利用动态...
"动态规划算法实现投资问题" 资源分配问题是指在给定的总资源下,如何将其分配给多个工程项目,以获得最大利润的问题。这种问题可以使用动态规划算法来解决。 在动态规划算法中,我们首先需要定义状态变量,例如...
【背包问题动态规划算法模拟设计与实现】 背包问题是一类经典的优化问题,在计算机科学和运筹学中广泛应用。它的核心是通过有限的资源(背包的容量)来最大化收益(子物品的价值)。0-1背包问题是最基础的形式,...
"动态规划算法原理与应用" 动态规划是一种解决最优化问题的基本方法,它可以分解为多个互相联系的阶段,每个阶段都需要进行决策,以达到目标函数的极大或极小。动态规划的主要思想是将问题实例分解为更小的、相似的...
《动态规划算法实验》实验报告主要探讨了两个经典动态规划问题——0-1背包问题和合唱队形安排问题。这两个问题都是在优化决策过程中寻找最优解的经典实例。 **一、0-1背包问题** 0-1背包问题是一个经典的约束优化...
子问题重叠是动态规划算法效率的关键,即在解决问题的过程中,某些子问题会被多次求解。通过存储子问题的解,我们可以避免重复计算,提高效率。这也是动态规划与分治法的主要区别,后者通常处理独立的子问题。 设计...
动态规划算法是一种在计算机科学和生物学领域广泛应用的解决复杂问题的方法。在本场景中,它被用来比对蛋白质序列,这是生物信息学中的一个核心任务。蛋白质序列比对旨在寻找两个或多个蛋白质序列之间的相似性,这...
这12个动态规划算法的程序代码是解决此类问题的实例,使用了C++编程语言,适用于后端开发。 动态规划的基本思想是将一个复杂问题分解为若干个子问题,通过求解子问题的最优解来得到原问题的最优解。在水库调度问题...
【达摩老生出品,必属...资源名:matlab实现动态规划算法 程序源码.zip 资源类型:程序源代码 源码说明: 基于matlab实现动态规划的程序,包含完整源码和注释,非常适合借鉴学习 适合人群:新手及有一定经验的开发人员
数据结构动态规划算法总结 动态规划是一种重要的算法思想,广泛应用于经济管理、生产调度、工程技术和最优控制等方面。动态规划是解决多阶段决策过程的优化问题的数学方法,由美国数学家R.E.Bellman等人在20世纪50...
动态规划算法是计算机科学与运筹学中一项关键的策略,它广泛应用于求解多阶段决策问题。这类问题往往具有以下特点:在求解过程中需要分为多个阶段,每个阶段都面临一个选择,决策者的最终目标是找出一条从开始到结束...
动态规划算法是一种强大的工具,常用于解决复杂的问题,如寻找最优化解。在这个实验报告中,我们关注的是如何运用动态规划解决数塔问题。数塔问题是一个典型的动态规划实例,它要求从一个下三角矩阵的顶部出发,找到...
### 动态规划算法与贪心算法 #### 最优化原理 最优化原理是解决多阶段决策问题的关键。这一原理最早由美国数学家R. Bellman等人于1951年提出,他们指出:一个最优策略的子策略对于它的初态和终态而言也必须是最优...
利用动态规划算法解决图形图像处理问题,用Java编写,代码经过调试健壮性良好
动态规划算法作为一种强大的编程策略,尤其在解决具有重叠子问题和最优子结构特性的问题时,展现出了其独特的魅力。然而,在实际应用中,尤其是在ACM等编程竞赛中,动态规划算法的时间效率优化成为了参赛选手关注的...
总的来说,这个C++实现的0-1背包问题动态规划算法不仅展示了如何利用动态规划解决问题,还提供了代码调试和测试的方法,是学习和理解动态规划算法的一个优秀实例。通过深入研究和实践,我们可以掌握这一重要的算法...