大家好,又见面了,我是你们的朋友全栈君。
一.回溯法
回溯法采用的是深度优先策略,回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。 (1)三个步骤: 1.针对所给问题,定义问题的解空间; 2.确定易于搜索的解空间结构; 3. 以深度优先的方式搜索解空间。 (2)优化方法: 搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类: 1.使用约束函数,剪去不满足约束条件的路径。 2.使用限界函数,剪去不能得到最优解的路径。
(3)解空间树的类型分为排列树和子集树。
二.0-1背包问题
问题:给定n种物品和一背包。物品i的重量是wi,其价值为pi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
1 #include <iostream>
2 using namespace std;
3
4 #define N 100 //默认有99个物品。第一个不使用
5 int w[N]; //每个物品的重量
6 int v[N]; //每个物品的价值
7 int x[N]; //x[i]=1:物品i放入背包,0代表不放入
8 int n,c; //n:一共有多少物品,c:背包的最大容量
9
10 int CurWeight = 0; //当前放入背包的物品总重量
11 int CurValue = 0; //当前放入背包的物品总价值
12
13 int BestValue = 0; //最优值;当前的最大价值,初始化为0
14 int BestX[N]; //最优解;BestX[i]=1代表物品i放入背包,0代表不放入
15
16 /*
17 *回溯函数 参数t表示当前处在第几层做抉择,t=1时表示当前在决定是否将第一个物品放入背包
18 */
19 void backtrack(int t)
20 {
21 //叶子节点,输出结果
22 if(t>n)
23 {
24 //如果找到了一个更优的解
25 if(CurValue>BestValue)
26 {
27 //保存更优的值和解
28 BestValue = CurValue;
29 for(int i=1; i<=n; ++i)
30 BestX[i] = x[i];
31 }
32 }
33 else
34 {
35 //遍历当前节点的子节点:0 不放入背包,1放入背包
36 for(int i=0; i<=1; ++i)
37 {
38 x[t]=i;
39
40 if(i==0) //不放入背包
41 {
42 backtrack(t+1);
43 }
44 else //放入背包
45 {
46 //约束条件:当前物品是否放的下
47 if((CurWeight+w[t])<=c)
48 {
49 CurWeight += w[t];
50 CurValue += v[t];
51 backtrack(t+1);
52 CurWeight -= w[t];
53 CurValue -= v[t];
54 }
55 }
56 }
57 }
58 }
59
60 int main()
61 {
62
63 cout<<"请输入物品的个数:"<<endl;
64 cin>>n;
65 cout<<"请输入每个物品的重量及价值(如5 4):"<<endl;
66 for(int i = 1; i <= n; i++)
67 {
68 cin>>w[i]>>v[i];
69 }
70 cout<<"请输入背包的限制容量:"<<endl;
71 cin>>c;
72
73 backtrack(1);
74
75 cout<<"最优值是:"<<BestValue<<endl;
76 cout<<"(";
77 for(int i=1;i<=n;i++)
78 cout<<BestX[i]<<" ";
79 cout<<")";
80 return 0;
81 } 1 #include <iostream>
2 using namespace std;
3
4 #define N 100 //默认有99个物品。第一个不使用
5 int w[N]; //每个物品的重量
6 int v[N]; //每个物品的价值
7 int x[N]; //x[i]=1:物品i放入背包,0代表不放入
8 int n,c; //n:一共有多少物品,c:背包的最大容量
9
10 int CurWeight = 0; //当前放入背包的物品总重量
11 int CurValue = 0; //当前放入背包的物品总价值
12
13 int BestValue = 0; //最优值;当前的最大价值,初始化为0
14 int BestX[N]; //最优解;BestX[i]=1代表物品i放入背包,0代表不放入
15
16 void input()
17 {
18 cout<<"请输入物品的个数:"<<endl;
19 cin>>n;
20 cout<<"请输入每个物品的重量及价值(如5 4):"<<endl;
21 for(int i = 1; i <= n; i++)
22 {
23 cin>>w[i]>>v[i];
24 }
25 cout<<"请输入背包的容量:"<<endl;
26 cin>>c;
27 }
28 void output()
29 {
30 cout<<"最优值是:"<<BestValue<<endl;
31 cout<<"(";
32 for(int i=1;i<=n;i++)
33 cout<<BestX[i]<<" ";
34 cout<<")";
35
36 }
37 /*
38 *回溯函数 参数t表示当前处在第几层做抉择,t=1时表示当前在决定是否将第一个物品放入背包
39 */
40 void backtrack(int t,int CurWeight,int CurValue,int rw,int x[])
41 {
42 //初始调用时rw为所有物品重量和
43 if(t>n)
44 {
45 //如果找到了一个更优的解
46 if(CurWeight==c&&CurValue>BestValue)
47 {
48 //保存更优的值和解
49 BestValue = CurValue;
50 for(int i=1; i<=n; ++i)
51 BestX[i] = x[i];
52 }
53 }
54 else
55 {
56 //遍历当前节点的子节点:0 不放入背包,1放入背包
57 if(CurWeight+w[t]<=c) //左孩子结点剪枝
58 {
59 x[t]=1;//选取第i个物品回溯
60 backtrack(t+1,CurWeight+w[t],CurValue+v[t],rw-w[t],x);
61 }
62 x[t]=0;//不选取第i个物品回溯
63 if(CurWeight+rw>c)//右孩子结点剪枝
64 backtrack(t+1,CurWeight,CurValue,rw-w[t],x); //rw都减去w[t]代表已经考虑过是否选取当前物品,不必再考虑
65 }
66
67 }
68
69 int main()
70 {
71
72 input();
73 backtrack(1,0,0,11,x);
74 output();
75 return 0;
76 }

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/155436.html原文链接:https://javaforall.cn