一、实验目的
1 理解贪心法的特征(最优子结构\贪心选择\局部最优)
2 理解贪心法的求解(划分过程\根据贪心策略做出选择,规模变小\求解子问题)
3 掌握贪心法的简单实现和时间复杂度分析
二、实验内容
1、背包问题
2、找零钱问题
3、图着色问题
三、问题分析
1、背包问题
因为不是0/1问题,所以要根据物品的单位价值进行降序排列,先把单位价值大的物品装入背包,然后如果背包还有空间的话,再把剩余的物品按照比例放入背包当中
2、找零钱问题
依旧是先把纸币的值按照降序排列,每次都去判断要找的钱是否大于最大的纸币,大于则就用大纸币,然后将要找的钱数缩小
3、图着色问题
依次遍历每个顶点,判断这个顶点与前后的顶点有没有相连,颜色有没有相同,以此来进行着色
四、问题解决
1、背包问题:
(1)、算法描述:
算法:KnapSack
输入:背包容量C,物品重量w[],物品价值v[]
输出:背包的最大价值
过程:1、让w[],v[]两个数组按照单位重量价值降序排列
2、定义一个长度为n的数组,并将其初始化为0
3、考虑单位重量价值最大的物品:i=1
4、循环知道wi >C
4.1、将第i个物品放入背包
4.2、C=C-wi;
4.3、i++;
5、最后装入的物品:xi=C/wi
(2)、代码:
该算法的时间复杂度为:O(nlogn)
(3)、运行截图:
2、找零钱问题:
(1)、算法描述:
算法:PayMoney
输入:找的钱数sum,纸币种类m[]
输出:找的纸币数量
过程:1、定义整形变量count
2、只要sum>0,就重复执行以下操作
2.1、循环变量i从0到m[]数组长度,重复以下操作
2.1.1如sum>=m[i],则count++;sum=sum-m[i];break;
2.2i++、
4、返回count
(2)、代码:
该算法时间复杂度为:O(n)
(3)、运行截图“
3、图着色问题:
(1)、算法描述:
算法:ColorGraph
输入:无向图G=(V,E)
输出:最小色数
过程:1、所有顶点置未着色状态;颜色k初始化为0;
2、循环知道所有顶点均着色
2.1、取下一种颜色k++;
2.2、循环变量i从1至n依次考查所有顶点
2.2.1若顶点i已经着色,则转步骤2.2,考查下一个顶点
2.2.2若顶点i着颜色k不冲突,则color[i]=k;
3、输出各顶点的着色
(2)、代码:
该算法的时间复杂度为O(k*n)
(3)、运行截图:
五、实验结果总结
回答以下问题:
- 请从你实现的级别中选择一题,说明贪心法的解决过程(划分阶段、依据贪心策略做出选择、求解子问题)
对于背包问题,对物品进行降序排列之后,依次判断物品的重量是都小于背包的容量,如果小于则直接放入背包当中,直到不能够完整放下去之后,再对物品进行切割,按照比例装入背包,计算背包价值
- 你觉得贪心法、动态规划法、分治法有相同点吗?有不同点吗?请举例说明。
有相同点,它们都是将问题实例归纳为更小的相似的子问题,并通过求解子问题产生一个全局最优解;也有不同点,其中贪心法的当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问题;而分治法中的各个子问题是独立的 (即不包含公共的子子问题),因此一旦递归地求出各子问题的解后,便可自下而上地将子问题的解合并成问题的解。动态规划则是主要应用于最优化问题,这类问题会有多种可能的解,每个解都有一个值,而动态规划找出其中最优(最大或最小)值的解。
- 你觉得贪心法能用递归实现吗?如果能,请把你实现的一道题目改为贪心法的递归程序。
可以通过递归实现。
对于图着色问题的递归算法:
void trycolor(int s,Graph G)/*填颜色,s为开始图色的顶点,本算法从1开始*/
{
int i;
if(s>G.vnum){/*如果s大于顶点的个数,递归出口*/
output(G);
exit(1);
}else{
for(i=1;i<=N;i++){/*对每一种色彩逐个测试*/
color[s]=i;
//如果flag=1进行下一种颜色的测试
if(colorsame(s,G)==0){
trycolor(s+1,G);/*进行下一块的着色*/
break;
}
}
}
}