警告
本文最后更新于 2018-06-16,文中内容可能已过时。
弱鸡还是弱鸡啊最简单的背包问题——。——!
1 问题描述
假设有一个能装入总体积为 T 的背包和 n 件体积分别为 W1,W2,···,Wn 的物品,能否从 n 件物品中挑选若干件恰好装满背包,即使 W1+W2+···+Wn=T,要求找出所有满足上述条件的解。例如:当 T=10,共 6 件物品,物品的体积为{1,2,3,4,5,8},那么可找到下列 4 组解:(1,2,3,4)、(1,4,5)、(2,3,5)、(2、8)。
2 实现提示
可利用回溯法的设计思想来解决背包问题。首先,将物品排成一列,然后顺序选取物品装入背包,假设已选取了前 i 件物品之后背包还没有装满,则继续选取第 i+1 件物品,若该件物品“太大”不能装入,则丢弃而继续选取下一件,直至背包装满为止。但如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入背包的那件物品“不合适”,应将它取出“丢弃一边”,继续再从“它之后”的物品中选取,如此重复,直至求得满足条件的解,或者无解。由于回溯求解的规则是“后进先出”,因此要用到栈。
使用栈作为该程序的数据结构,利用栈进行语法检查,以深度优先的搜索方式解空间,实现递归过程和函数的调用,在设计时还使用 C 语言的数组及其循环语言来实现程序。
运用回溯法解题,在搜索解空间树时,只要其左儿子节点是一个可行结点,搜索就进入左子树,在右子树中有可能包含最优解是才进入右子树搜索。否则将右子树剪去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
| #include <stdio.h>
#include <windows.h>
#define size 50
struct stacks {
int data[size];
int top;
} stack;
void backpack(int number,int V,int w[]){
int i,j=1,k=0;
int flag=0;
do {
while (V > 0 && k <= number) {
if (V >= w[k]) {
stack.data[stack.top] = k;//第 k 个物品的体积下标
stack.top++;
V -= w[k];
}
k++;
}
if (V == 0) {
flag=1;
printf("第%d 个符合条件的解:", j);
for (i = 0; i < stack.top; i++) {
printf("%d ", w[stack.data[i]]);
}
j++;
printf("\n");
}
//k 满时回溯
k = stack.data[--stack.top];
stack.data[stack.top] = 0;
V += w[k];
k++;
} while (!(stack.top == 0 && k == number));
if(!flag){
printf("背包无解!\n");
}
}
void judge(int number,int V,int w[]){
int i,s = 0;
for (i = 0; i < number; i++)
s = s + w[i];
if(V > s){
printf("背包无解!\n");
exit(0);
}
if(V==s){
printf("只有一个符合条件的解:%d\n", V);
exit(0);
}
}
int main() {
int w[size];
int V;
int i = 0;
int j = 0;
int number;
printf("\t **简单背包问题**\n\n");
printf("\n 请输入可供选择装入物品的个数:\n");
scanf("%d", &number);
printf("\n 请输入各件物品的体积:\n");
for (i = 0; i < number; i++)
scanf("%d", &w[i]);
//排序
for(i=0;i<number;i++)
for(j=i+1;j<number;j++)
if(w[i]>w[j]){
w[i]=w[i]^w[j];
w[j]=w[i]^w[j];
w[i]=w[i]^w[j];
}
printf("\n 请输入背包的总体积:\n");
scanf("%d", &V);
while(V < 0){
printf("输入背包体积错误!重新输入!\n");
scanf("%d",&V);
}
judge(number,V,w);
//初始化栈
for (i = 0; i < number; i++)
stack.data[i] = 0;
stack.top = 0;
backpack(number,V,w);
return 0;
}
|
–这么简单的问题我都费力,太辣鸡了,还是要多练习啊!–