贪心算法背包问题c

在背包问题中,贪心算法通常用来解决0-1背包问题,也就是每种物品都有固定数量,你可以选择拿或者不拿,但不可以拿走部分。以下是一个用C语言实现的贪心算法的例子:

  1. #include <stdio.h>
  2. #define MAX_N 1000
  3. #define MAX_W 100000
  4. int n, W;
  5. int w[MAX_N], v[MAX_N], s[MAX_N];
  6. int f[MAX_N][MAX_W];
  7. int max(int a, int b) {
  8.     return a > b ? a : b;
  9. }
  10. int min(int a, int b) {
  11.     return a < b ? a : b;
  12. }
  13. int main() {
  14.     scanf("%d %d", &n, &W);
  15.     for (int i = 0; i < n; i++) {
  16.         scanf("%d %d %d", &w[i], &v[i], &s[i]);
  17.     }
  18.     for (int i = 0; i < n; i++) {
  19.         for (int j = W; j >= w[i]; j--) {
  20.             f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i]);
  21.         }
  22.     }
  23.     printf("%d\n", f[n - 1][W]);
  24.     return 0;
  25. }

在这个例子中,输入包括物品的数量n和背包的总容量W,然后是每个物品的重量w[i],价值v[i]和数量s[i]。在这个版本的背包问题中,每个物品可以取多次。f[i][j]表示在容量为j的背包中,前i个物品能够获得的最大价值。程序最后输出的是在给定背包容量下,所有物品的最大价值。

背包问题的贪心算法主要是针对0-1背包问题,即每种物品都有固定数量,可以选择拿或者不拿,但不可以拿走部分。贪心算法的策略是在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的。

在背包问题中,我们通常用动态规划来求解。在上述代码中,我们用f[i][j]表示前i个物品在容量为j的背包中能够获得的最大价值。初始状态是f[0][j] = 0,表示不取任何物品时的价值为0。然后我们依次考虑每个物品,对于每个物品,我们都尝试放入背包中,并更新f[i][j]。

对于每个物品i,我们从背包容量W开始考虑,逐步减小背包容量,直到背包容量小于物品i的重量。在这个过程中,我们希望找到一个最小的背包容量,使得放入物品i后能够获得最大的价值。这个最小的背包容量就是f[i - 1][j - w[i]],表示前i - 1个物品在容量为j - w[i]的背包中能够获得的最大价值。如果我们将物品i放入容量为j - w[i]的背包中,那么这个背包的容量就增加了w[i],所以能够获得的最大价值就是f[i - 1][j - w[i]] + v[i]。

因此,我们可以得到状态转移方程:f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i])。这个状态转移方程表示,对于前i个物品在容量为j的背包中能够获得的最大价值f[i][j],要么是前i个物品在容量为j的背包中能够获得的最大价值f[i][j],要么是前i - 1个物品在容量为j - w[i]的背包中能够获得的最大价值f[i - 1][j - w[i]] + v[i]。

最后,输出f[n - 1][W],表示前n个物品在容量为W的背包中能够获得的最大价值。

除了上述的贪心算法外,还有一种称为“完全背包”的贪心算法,适用于物品数量不固定的情况。

在完全背包问题中,每种物品的数量是无限的,可以选择拿或者不拿,但不可以拿走部分。以下是一个用C语言实现的完全背包问题的贪心算法:

  1. #include <stdio.h>
  2. #define MAX_N 1000
  3. #define MAX_W 100000
  4. int n, W;
  5. int w[MAX_N], v[MAX_N];
  6. int f[MAX_N][MAX_W];
  7. int max(int a, int b) {
  8.     return a > b ? a : b;
  9. }
  10. int min(int a, int b) {
  11.     return a < b ? a : b;
  12. }
  13. int main() {
  14.     scanf("%d %d", &n, &W);
  15.     for (int i = 0; i < n; i++) {
  16.         scanf("%d %d", &w[i], &v[i]);
  17.     }
  18.     for (int i = 0; i < n; i++) {
  19.         for (int j = w[i]; j <= W; j++) {
  20.             f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i]);
  21.         }
  22.     }
  23.     printf("%d\n", f[n - 1][W]);
  24.     return 0;
  25. }

在这个例子中,输入包括物品的数量n和背包的总容量W,然后是每个物品的重量w[i]和价值v[i]。在这个版本的背包问题中,每种物品的数量是无限的,可以选择拿或者不拿,但不可以拿走部分。我们用f[i][j]表示前i个物品在容量为j的背包中能够获得的最大价值。程序最后输出的是在给定背包容量下,所有物品的最大价值。

在完全背包问题中,由于每种物品的数量是无限的,所以可以将每个物品看作是一个整体,而不必考虑其数量。因此,我们可以将每个物品的重量和价值看作是其整体的“单位重量”和“单位价值”。

在贪心算法中,我们采取的策略是在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的。因此,我们可以将每个物品的单位价值除以单位重量得到一个“性价比”,然后按照性价比从高到低的顺序依次考虑每个物品。

具体实现时,我们可以先计算每个物品的单位重量和单位价值,然后按照单位价值的降序排列每个物品。对于每个物品,我们可以依次将其加入背包中,并更新背包的容量和价值。这个过程中需要用到一个二维数组f[i][j],表示前i个物品在容量为j的背包中能够获得的最大价值。

状态转移方程与上面的背包问题类似,可以用以下公式表示:

f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i])其中w[i]表示第i个物品的重量,v[i]表示第i个物品的价值。

最后输出f[n - 1][W],表示前n个物品在容量为W的背包中能够获得的最大价值。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
贪心算法是一种常见的近似算法,用于在图论、排队问题、选择问题等多种实际问题中求解最优解。而背包问题是一个经典的优化问题,是贪心算法常用的应用之一。 以下是一个贪心算法背包问题的C语言代码: #include <stdio.h> int main() { int n, i, j, w[100], v[100], c, ans = 0; float t; //比率 printf("请输入背包数量和可容纳重量:\n"); scanf("%d %d", &n, &c); printf("请输入每个背包的重量和价值:\n"); for (i = 1; i <= n; i++) { scanf("%d %d", &w[i], &v[i]); } //计算每个背包的比率,按比率排序 for (i = 1; i <= n; i++) { for (j = i + 1; j <= n; j++) { if ((float) v[i] / w[i] < (float) v[j] / w[j]) { t = (float) v[i] / w[i]; v[i] = v[j]; w[i] = w[j]; v[j] = (int) (v[i] / t); w[j] = (int) (w[i] / t); } } } //不断选取比率最高的背包 for (i = 1; i <= n && c > 0; i++) { if (w[i] <= c) { ans += v[i]; c -= w[i]; } else { ans += (int) (v[i] * ((float) c / w[i])); c = 0; } } printf("该背包能够获取的最大价值为:%d", ans); return 0; } 输入数据后,程序首先计算每个背包的比率,按比率从高到低排序。接下来,程序从比率最高的背包开始,一直按比率选取背包,直到无法再选取为止。在选取背包时,程序优先选取可以直接放进背包的背包,如果一个背包无法完全放进背包,程序则按比率选取部分放进背包。最后,程序输出可获取的最大价值。 以上是一个简单的贪心算法背包问题C语言代码。通过这个例子,我们可以看到贪心算法的两个重要特点:1. 每一步只考虑当前最优解。2. 最终结果必须为最优解。但是,贪心算法也有其局限性,它不一定能够找到全局最优解,而只能得到一个近似最优解。因此,在实际应用中,我们需要结合问题特点,选择合适的算法,避免贪心算法带来的误差。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

crmeb专业二开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值