软考路——算法其实很简单

在参加中级软件设计师的考试中,公认的最难的一部分就是算法。可是自从老师给我们讲完算法之后,就感觉算法其实也没什么。软考中,算法被分为分治法、动态规划法、贪心算法和回溯法。那么,今天我们就来说一说这几种算法。

一、概念

1、分治法

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归的解这些子问题,然后将各子问题的解合并得到原问题的解。

适用范围:

   1) 该问题的规模缩小到一定的程度就可以容易地解决

  2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。

  3) 利用该问题分解出的子问题的解可以合并为该问题的解;

   4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

2、动态规划

和分治法一样,动态规划(dynamic programing)是通过组合子问题的解而解决整个问题的。不过与分治法不一样的地方就是,分解得到的子问题往往不是独立的,也就是说相同的子问题可能会被求解多次。

适用范围:

   1) 最优子结构性质:一个最优化策略的子策略总是最优的。

   2) 无后效性:每个状态都是过去历史的一个完整总结。

   1) 子问题的重叠性:是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。

3、贪心

贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。

当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

4、回溯

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

    适用范围

在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。

二、背包问题

1、贪心思想

背包问题

      背包问题:与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。

给定n个物品和一个容量为C的背包,物品i的重量是Wi,其价值为Vi。 背包问题是如何选择入背包的物品,使得装入背包的物品的总价值最大,注意和0/1背包的区别,在背包问题中可以将物品的一部分装入背包,但不能重复装入。

三种解决方案

(1)选择价值最大的物品优先,因为这可以尽可能快的增加背包的总价值,但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗的太快,使得装入背包的物品个数减少,从而不能保证目标函数达到最大。

(2)选择重量最轻的物品,因为这可以装入尽可能多的物品,从而增加背包的总价值。但是,虽然每一步选择使背包的容量消耗的慢了,但背包的价值却没能保证迅速的增长,从而不能保证目标函数达到最大。

(3)性价比最高,以上两种贪心策略或者只考虑背包价值的增长,或者只考虑背包容量的消耗,而为了求得背包问题的最优解,需要在背包价值增长和背包容量消耗二者之间寻找平衡。正确的贪心策略是选择单位重量价值最大的物品。

PS:由此可见,贪心的最高境界就是什么都贪,它不仅仅贪某一方面,而是综合各个方面的贪。这也是所有人的想法——贪,正是由于我们有这种贪的想法,才得出之后的一些个算法。

2、回溯法

0-1背包问题

        给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有2种选择,即装入背包(1)或不装入背包(0)。不能将物品i装入背包多次,也不能只装入部分的物品i。

 解决方案

(1)未优化

虽然0-1背包问题与背包问题不一样,但是它们都很贪,都是为了使包中的总价值最大。由于,在贪心算法中,我们已经知道了按照单位重量价值最大的先放才会使包中总价值最大,所以在回溯法中,同样按照重量价值最大的先放,不过,每一个物品分为两种情况,放入(用1表示)或不放入(用0表示)。

所以可以根据这些条件,构造一个二叉树,该算法遍历每一条路径(从根节点到最底层算一条路劲),然后算出每条路径得到的包的总价值,然后比较得到最大的总价值。

(2)优化

由于二叉树会产生很多分支,如果每个都遍历一遍,效率是很低的,因此,为了提高算法的效率,我们可以使用限界函数,其作用是缩小我们遍历的范围。

在0-1背包中,我们是按照贪心算法来实现的限界函数,每次放入或不放入背包时,我们求出放入后或不放入背包后的贪心最优解(贪心算法处理背包问题的最优解),然后根据比较结果,我们遍历贪心最优解较大的一边。当遍历到底之后,回溯直到发现其他可遍历的点,然后继续比较,循环。

这样,我们就能保证,每次都是从贪心最优解较大的节点开始遍历,从而使我们的遍历更接近最优解。

3、动态规划

对于0-1背包问题,动态规划采用分治的方法来考虑,我们可以想象当背包容量很小的时候,可能进入背包的物品也相对变少(因为有些物品的重量已经超过了背包容量),那么为了使背包总价值最大,我们选择它进不进背包,就很容易。但简而言之,当背包容量大的时候,可选项多,当背包容量小的时候,可选项(可选择进入物品)较少,因此使问题得到简化。

我们如何将背包问题简化呢?那就是将放入背包问题转化为取出背包问题,什么意思呢?就是说,我们先假设所有的物品都在背包中,然后随机拿出一个,然后根据以下情况求其最优解,最优解还要在剩余的几个物品中求解,所以我们继续往外拿,如此递归,直至背包中物品为0。

这里是书上的式子,

 PS:i表示背包中物品总数,w表示背包所能承受的最大重量,Wi表示第i个物品的重量。c[i,w]表示背包重量为w,放入i个物品所得到的最大价值。

其实,这个不是什么公式,这只是分为三种情况

(1)第一种情况0,不用说,是当背包中物品为0,或背包重量为0时。此时价值自然为0.

(2)第二种情况为C[i-1,w],说明取出第i个物品后,背包重量不变,也就是说,该物品本来就不在背包中。此时是Wi>W,即取出第i个物品的重量大于背包重量,也就是该物品本来就不在背包中。

(3)第三种情况是说,取出的这个物品的重量小于背包时,它之前可能在背包中,也可能不在背包中,然后分别比较这两种情况的总价值。

针对上面的表达式,强调两点

第一点:我们对两种不同情况都利用了分治方法,但是这两种情况下的子问题的是不一样的,因为这两个子问题的约束条件不一样,一个背包容量为W-Wi,另一个为W。

第二点:我们看到要想求这两种情况下,谁的总价值大,必须依赖于前一个子问题的最优解。只有前一个子问题求解出来之后,当前问题才能解决。而在考虑前一个子问题的最优解时,我们还是以相同的方式,任选一个待考虑的物品,看它在背包里导致的子问题的价值大,还是不在里面导致的子问题的价值大。

PS:动态规划算法就在于动态和规划两个词,动态指,计算过程中随着那出物品,包的重量在动态减小;规划指,在计算过程中,通过在之前最优解上的比较情况,得出现在的最优解。

总结:

综上,我们知道了每一种算法都有其适用的情况,我们要根据实际情况来选择适当的算法。当然,我个人认为,所有的算法都是从贪心出发,以分而治之的方法解决。对于算法更深层次的理解,还需要我们在今后实际使用的过程中慢慢体会。

时间: 2024-12-18 11:11:09

软考路——算法其实很简单的相关文章

软考路——码的世界

参加了软考之后,第一次接触到了计算机系统知识的内容,其主要介绍了计算机的结构组成,以及计算机的原理,都是一些很抽象的东西. 大家都知道计算机中的运算都是通过二进制进行的,但是由于计算机中只有加法运算器,所以在进行减法运算往往会出错,这也就要求我们要把减法运算转化为加法运算.于是就出现了各种码. 1.原码 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制: [+1]原 = 0000 0001 [-1]原 = 1000 0001 原码是人脑最容易理解和计算

软考路——封装产生的虚拟空间

曾经,还在为看不懂的代码而发愁,曾经,还在为想不通的二进制转换而苦恼,而现在,却朝着软件设计师迈进.我们在不经意间,就会发生意想不到的变化.这是进步,也是成长. 在这个过程中,我可以得到很多,也会失去些什么,不过这些经历,是我生命中宝贵的财富.我想记录下来,然后分享给大家,让我们一同进步. 1.背景 正如我们所知道的一样,任何程序在计算机中运行都需要一个运行空间,可是在实存管理技术中,常常会出现以下问题: 1)要求运行的进程所需的内存空间大于系统的内存空间,只有部分进程能够装入内存运行,而其他进

【软考】向上转型 VS 简单工厂

今天我们不讲概念,先一起看一段程序. public class Test{ public static void main(String args[]){ Test test=new Test(); Animal a=new Animal("name"); Cat c=new Cat("catname","name"); Dog d=new Dog("dogname","black"); test.f(a)

软考之算法

继上篇文章写到关于数据结构的了解,有了数据结构自然要有算法了,下面来看看关于算法的理解! 算法在考试中要求级别是非常高的,是考试中的重点难点.所以要好好重视起来. 下面是我画的一张图: 算法分为查找和排序. 查找中,顺序查找,二分查找的方法和特点,在学习这两种查找方式时可以对比着学习,这样会有更高的效率.备考级别(***). 关于排序中的简单选择排序,直接插入排序和冒泡排序是考试中的重点.备考级别(***). 希尔排序,堆排序,归并排序和快速排序需要我们掌握方法和特点.备考级别(**). 在学习

软考路——Pk适配器模式

一.适配器模式 1.概念 将一个类的接口转换成客户希望的另外一个接口.A d a p t e r 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 2.对象适配器 使用对象组合,以修改的接口包装被适配者,被适配者的任何子类,都可以搭配着适配器使用. 把客户和接口绑定起来,而不是和实现绑定起来. 我们可以使用数个适配器,每一个都负责转换不同的后台类. 3.类适配器 类适配器,你需要多重继承才能实现它,这在Java和C#中是不可能的.但是当你使用多重继承语言的时候,还是可能遇到这样的需

软考路——进程与线程

一.进程 1.概念 程序是一组指令的有序集合.进程(Process)是具有一定独立功能的程序在一个数据集合上的一次运行活动.是系统进行资源分配和调度的一个独立单位. 程序本身没有任何运行的含义,只是一个静态实体.而进程则不同,它是程序在某个数据集上的执行,是一个动态实体.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程. 2.特性 (1)结构性 进程包含程序及其相关数据结构.进程的实体包含进程控制块(PCB),程

软考之路--开始的开始,我们都是孩子

为了软考,奋力一搏,没钱.没人脉.没背景,在人人自危的竞争中,要靠自己的真实力,这次考试我们积极备考,不打无准备之战,软考的目的,不仅仅是为了软考通过这么简单,在软考的背后还隐藏着一个古老的秘密,那就是为了学习知识,在个人重构,机房合作,牛腩新闻发布系统等学习中,小伙伴们有没有这样的疑问,出现了很多问题,解决了,但是具体的原理自己并不是很理解,这个时候,软考来了,驾着五彩的云霞,翩翩来到你眼前,解决我们计算机体系知识不全的问题.在面临自考,等级考,软考,计算机学习,英语学习等犹如冰糖葫芦的串儿的

拿什么应对你我的软考

话说软考也马上要开水一个月了,但是对于软考还不是很理解,今天就让我们来聊一聊那些年一起经历过的软考! 软考是全国计算机技术与软件专业技术资格(水平)考试(简称计算机与软件考试)是由国家人力资源和社会保障部与工业和信息化部组织领导的国家级考试,目的是科学.公正地对全国计算机与软件专业技术人员进行专业技术资格.职业资格认定和专业技术水平测试. 所以说软考是中国计算机界最高水平的考试!通过了考试下边这张图就可以用来描述你了! 那么在未来你就可以很坦然来做这些事情!看车,看房,看包包,还可以大胆的扶老奶

说说我的软考

软考结束了,让我说点什么好呢?说道结束,或许还不是结束!结果没有下来,就意味着,还有再学习一遍的必要. 一.软考话痨 软考毕竟是有章可循,所以是仁者见仁,智者见智.但是还是有一定的"对"和"错"的界限.二个月的时间,有差不多一个月的时间是供大家在一起供大家一起交流的.可以发现,不同的思维在交织,碰撞:当然还有一些意想不到的人,出乎意料的让你重新对待. 恍然大悟的是在学习交流的过程中,深深的发现最炙手可热的知识居然是年少无知的我浪费掉的专业课.或许应该庆幸,这提醒我: