贪心算法和动态规划有异曲同工之秒,能用贪心法的,就不用动规。我只想说,动态规划真TM难。
贪心算法这样一个算法,它在每一步都做出在当时看来是最优的方案,即它总是做出局部最优的选择。然后构成一个全局最优解。贪心算法也是一个强有力的算法,很多问题都能用贪心算法来解决。下面就说说两个经典的问题,分数背包问题和哈夫曼(Huffman)编码。
分数背包问题
分数背包问题是这样的,假设有一个背包体积为W, 有一系列商品,他们的体积各不相同,找出获取商品价值最大的方案。分数背包问题和0-1背包问题的惟一区别在于,是否可以取商品的一部分。贪心算法可以求解分数背包问题,但无法求解0-1背包问题。
正如贪心算法一样,人总是贪的,如果真有这样一件事,我们当然希望全部拿走,但是奈何空间有限。为简单起见,假设所有数据都是整数,该问题的输入和输出如下所述:
输入:
第一行是一个整数m,表示商品的数量
第二行是m个整数,表示商品的价值
输出:
最大价值v
定义p = v / w,我们称之为性价比,很明显,我们当然应该取性价比最高的商品,即价值最高,体积最小。
比如一个体积为50的背包,有三件商品,体积和价值分别为
商品(i) | 1 | 2 | 3 |
体积(v) | 10 | 20 | 30 |
价值(w) | 60 | 100 | 120 |
性价比(p) | 6 | 5 | 4 |
所以我们先取商品1, 价值为60, 占10体积,还剩40体积,再取商品2,价值为100, 占20体积,还剩20体积,最后取20体积商品3,价值为4 * 20 = 80, 所以最优方案是60 + 100 + 80 = 240. 代码如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Objcect {
int c;
int v;
double p;
}Object;
int compare(const void* n1, const void* n2)
{
return ((struct Objcect*)n2)->p - ((struct Objcect*)n1)->p;
}
int main(void)
{
int m, w;
while(scanf("%d", &m), m)
{
struct Objcect* objs = (struct Objcect*)malloc(sizeof(struct Objcect) * m);
for(int i = 0; i != m;