用c语言实现01背包问题的四种解法
时间: 2023-08-27 21:27:56 浏览: 175
好的,我来为您介绍一下。
1.暴力递归法
这种方法是通过递归的方式来解决01背包问题的。对于每个物品,我们可以选择将其放入背包或者不放入背包,然后再考虑下一个物品。当考虑完所有的物品后,我们就可以得到一个解,然后再从所有的解中选择一个最优解。这种方法的时间复杂度为O(2^n),其中n为物品的个数,因为对于每个物品,我们都有两种选择。
下面是使用暴力递归法实现01背包问题的代码:
```c
#include <stdio.h>
int max(int a, int b) {
return a > b ? a : b;
}
int knapsack(int W, int wt[], int val[], int n) {
if (n == 0 || W == 0) {
return 0;
}
if (wt[n-1] > W) {
return knapsack(W, wt, val, n-1);
}
return max(val[n-1] + knapsack(W-wt[n-1], wt, val, n-1), knapsack(W, wt, val, n-1));
}
int main() {
int val[] = {60, 100, 120};
int wt[] = {10, 20, 30};
int W = 50;
int n = sizeof(val)/sizeof(val[0]);
printf("Maximum value: %d", knapsack(W, wt, val, n));
return 0;
}
```
2.动态规划法
动态规划法是通过构建一个二维数组来解决01背包问题的。我们可以将物品放入背包中,或者不将其放入背包中。我们可以将二维数组中的每个元素看做是一个子问题的解,然后我们可以通过递推的方式来求解整个问题的解。此方法的时间复杂度为O(nW),其中n为物品的个数,W为背包的容量。
下面是使用动态规划法实现01背包问题的代码:
```c
#include <stdio.h>
int max(int a, int b) {
return a > b ? a : b;
}
int knapsack(int W, int wt[], int val[], int n) {
int dp[n+1][W+1];
for (int i = 0; i <= n; i++) {
for (int w = 0; w <= W; w++) {
if (i == 0 || w == 0) {
dp[i][w] = 0;
} else if (wt[i-1] > w) {
dp[i][w] = dp[i-1][w];
} else {
dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]);
}
}
}
return dp[n][W];
}
int main() {
int val[] = {60, 100, 120};
int wt[] = {10, 20, 30};
int W = 50;
int n = sizeof(val)/sizeof(val[0]);
printf("Maximum value: %d", knapsack(W, wt, val, n));
return 0;
}
```
3.回溯法
回溯法是通过搜索所有可能的解来解决01背包问题的。在搜索的过程中,我们可以将物品放入背包中,或者不将其放入背包中。如果当前的背包容量已经超过了背包的容量,或者已经考虑完所有的物品,那么就可以得到一个解。然后再从所有的解中选择一个最优解。这种方法的时间复杂度为O(2^n),其中n为物品的个数。
下面是使用回溯法实现01背包问题的代码:
```c
#include <stdio.h>
int max(int a, int b) {
return a > b ? a : b;
}
void knapsack(int W, int wt[], int val[], int n, int curW, int curVal, int *maxVal) {
if (curW > W) {
return;
}
if (n == 0) {
*maxVal = max(*maxVal, curVal);
return;
}
knapsack(W, wt, val, n-1, curW, curVal, maxVal);
knapsack(W, wt, val, n-1, curW+wt[n-1], curVal+val[n-1], maxVal);
}
int main() {
int val[] = {60, 100, 120};
int wt[] = {10, 20, 30};
int W = 50;
int n = sizeof(val)/sizeof(val[0]);
int maxVal = 0;
knapsack(W, wt, val, n, 0, 0, &maxVal);
printf("Maximum value: %d", maxVal);
return 0;
}
```
4.分支限界法
分支限界法是通过搜索所有可能的解来解决01背包问题的。在搜索的过程中,我们可以将物品放入背包中,或者不将其放入背包中。但是我们在搜索的过程中,可以使用一些策略来减少搜索的次数。例如,我们可以将物品按照单位重量的价值排序,然后先考虑价值高的物品。这种方法的时间复杂度取决于使用的策略,但是一般来说,它的时间复杂度可以达到O(nlogn)。
下面是使用分支限界法实现01背包问题的代码:
```c
#include <stdio.h>
#include <stdlib.h>
typedef struct Item {
int val;
int wt;
double vw;
} Item;
int cmp(const void *a, const void *b) {
Item *ia = (Item *)a;
Item *ib = (Item *)b;
return ib->vw - ia->vw;
}
int bound(Item items[], int n, int W, int curW, int curVal) {
if (curW > W) {
return 0;
}
int boundVal = curVal;
int j = n;
int totW = curW;
while ((j < n) && (totW + items[j].wt <= W)) {
totW += items[j].wt;
boundVal += items[j].val;
j++;
}
if (j < n) {
boundVal += (W - totW) * items[j].vw;
}
return boundVal;
}
void knapsack(Item items[], int n, int W, int *maxVal) {
qsort(items, n, sizeof(Item), cmp);
int curW = 0, curVal = 0;
int i = 0;
int boundVal = bound(items, n, W, curW, curVal);
int Q[n];
Q[i] = 0;
while (i >= 0) {
int j = Q[i];
i--;
if (j == n) {
if (curVal > *maxVal) {
*maxVal = curVal;
}
continue;
}
if (curW + items[j].wt <= W) {
curW += items[j].wt;
curVal += items[j].val;
if (curVal > *maxVal) {
*maxVal = curVal;
}
boundVal = bound(items, n, W, curW, curVal);
if (boundVal > *maxVal) {
i++;
Q[i] = j+1;
}
curW -= items[j].wt;
curVal -= items[j].val;
}
boundVal = bound(items, n, W, curW, curVal);
if (boundVal > *maxVal) {
i++;
Q[i] = j+1;
}
}
}
int main() {
Item items[] = {{60, 10, 6}, {100, 20, 5}, {120, 30, 4}};
int n = sizeof(items)/sizeof(items[0]);
int W = 50;
int maxVal = 0;
knapsack(items, n, W, &maxVal);
printf("Maximum value: %d", maxVal);
return 0;
}
```
阅读全文