完全背包问题贪心算法c语言,数据结构与算法学习之路:背包问题的贪心算法和动态规划算法...

一、背包问题描述:

有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大。

二、解决方法:

1、贪心算法:贪心算法基于的思想是每一次选择都作当前最好的选择,这样最后的结果虽然不一定是最优解,但是也不会比最优解差很多。

举个例子说明可能好懂一些:一帮基友去聚餐,菜是一份一份上的,我每一次夹菜都只夹牛肉/海鲜吃,可能到最后我吃的牛肉/海鲜很多,但不一定代表我吃掉的东西的总价值最高,但是相对来说价值也很高了~

换句话说,对于贪心算法,其核心在于设定一个标准让我们去贪。回到这个问题,这个标准就有三种设法了:1、价值最高的先装进背包;2、重量最低的先装进包;3、性价比(价值和重量的比值)最高的先装进背包。我在这里用的是第三种方法,用快排作了排序。

在装的过程中要注意的就是,当前物品能不能放进背包。这个是需要考虑的。因为背包问题也有好几种,如:0-1背包问题(每种物品只能拿一次)、完全背包问题(每种物品都能拿无限次)、多重背包问题(每种物品都有一定的数量可以拿)。所以在不同情况下贪心算法的一些细节设计也是不一样的,这个需要自己考虑。

2、动态规划算法:贯穿动态规划算法的就是状态和状态转移方程这两个东西,而要得到这两个东西需要我们把我们的问题分解为更小的子问题,通过分析子问题去获得。这个我在LIS问题上也讲过(数据结构与算法学习之路:LIS——最长递增序列的动态规划算法和二分思想算法)

那么回到我们这个问题,由于每次装东西进背包,我们只考虑能否装进,以及是否当前状态下的最优选择,也就是说,我们需要用背包的容量去设计一个数组,存储每一单位个容量的最大价值是多少,以此类推,获得背包容量下的最大价值是多少。这样说可能说不清楚,看看下面的代码吧~

三、代码:

1、贪心算法:

void Greedy_KnapSack(Greedy_BagPtr greedy_bags, float bagWeight){

float temp = bagWeight;

Quick_Sort(greedy_bags, 0, 9);

for (int i = 9; i >= 0; --i){

if (greedy_bags[i].weight <= temp){

temp -= greedy_bags[i].weight;

greedy_bags[i].resultWeight = 1;

}

else if (greedy_bags[i].weight > temp && temp > 0){

greedy_bags[i].resultWeight = temp / greedy_bags[i].weight;

temp = 0;

}

else if (temp < 0)

return;

}

}

2、动态规划算法:

int DP_KnapSack(DP_BagPtr dp_bags, int bagWeight){

int i, size = bagWeight + 1,currentMaxValue;

int *dp_bagweight = (int*)malloc(size*sizeof(int));

dp_bagweight[0] = 0;

for (i = 1; i < size; ++i){

currentMaxValue = 0;

if (i <= 9 && i > 0){

for (int j = 0; j < BAGSIZE; ++j){

if (dp_bags[j].weight == i && dp_bags[j].value > currentMaxValue)

currentMaxValue = dp_bags[j].value;

}

if ((dp_bagweight[i - 1] + 1) > currentMaxValue)

dp_bagweight[i] = dp_bagweight[i - 1] + 1;

else

dp_bagweight[i] = currentMaxValue;

}

else{

if ((dp_bagweight[i - 1] + 1) > (dp_bagweight[9] + dp_bagweight[i % 9]))

dp_bagweight[i] = dp_bagweight[i - 1] + 1;

else

dp_bagweight[i] = dp_bagweight[9] + dp_bagweight[i % 9];

}

}

return dp_bagweight[bagWeight];

}

3、可能有人会需要,在解决这个问题的情况下我修改的快排

void Quick_Sort(Greedy_BagPtr bags, int start, int end){

if (start < end){

int i = start, j = end;

Greedy_Bag temp = bags[start];

while (i < j){

while (i < j && bags[j].relativeValue >= temp.relativeValue)

--j;

if (i < j)

bags[i++] = bags[j];

while (i < j && bags[i].relativeValue < temp.relativeValue)

++i;

if (i < j)

bags[j--] = bags[i];

}

bags[i].value = temp.value;

bags[i].weight = temp.weight;

bags[i].resultWeight = temp.resultWeight;

bags[i].relativeValue = temp.relativeValue;

Quick_Sort(bags, start, i - 1);

Quick_Sort(bags, i + 1, end);

}

}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
背包问题是一个经典的动态规划问题,贪心算法并不一定能得到最优解。但是,如果背包问题的物品的体积和价值比比较固定,可以使用贪心算法求解。以下是使用贪心算法解决背包问题C语言代码: ``` #include <stdio.h> // 物品结构体 struct item { int value; // 价值 int weight; // 重量 }; // 比较函数,按单位价值从大到小排序 int cmp(const void *a, const void *b) { struct item *ia = (struct item *)a; struct item *ib = (struct item *)b; double va = (double)ia->value / ia->weight; double vb = (double)ib->value / ib->weight; return (vb > va) - (vb < va); } // 贪心算法求解背包问题 double knapsack(int W, struct item items[], int n) { double total_value = 0.0; qsort(items, n, sizeof(struct item), cmp); // 按单位价值排序 for (int i = 0; i < n; i++) { if (W >= items[i].weight) { // 可以放入整个物品 total_value += items[i].value; W -= items[i].weight; } else { // 只能放入部分物品 total_value += (double)W / items[i].weight * items[i].value; break; } } return total_value; } int main() { int W = 50; // 背包容量 struct item items[] = { {60, 10}, {100, 20}, {120, 30}, }; int n = sizeof(items) / sizeof(items[0]); // 物品个数 double total_value = knapsack(W, items, n); printf("Total value: %.2f\n", total_value); return 0; } ``` 上述代码中,`cmp`函数用于按单位价值从大到小排序,`knapsack`函数用于实现贪心算法,`main`函数中的`items`数组表示物品的价值和重量,`n`表示物品的个数,`W`表示背包的容量。运行结果为: ``` Total value: 240.00 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值