回溯法解0-1背包问题实验报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(i=0;i<n;i++)
cin>>bag[i].w;
cout<<endl;
cout<<"请依次输入"<<n<<"个物品的价值P:"<<endl;
for(i=0;i<n;i++)
cin>>bag[i].v;
for(i=0;i<n;i++)
{
bag[i].flag=0;bag[i].kk=i;
bag[i].fl=1.0*bag[i].v/bag[i].w;
for(int k=0;k<n;k++)
{
x[bag[k].kk]=bag[k].flag; //x=0表示未放入背包,x=1表示放入背包
L+=bag[k].flag*bag[k].v; //价值累加
}
cout<<endl;
cout<<"当前最优价值为:"<<L<<endl;
cout<<"变量值x = ";
{
minl=li[j];swap(li[j],li[k]);k=j;
}
}
}
}
namespace jie //命名空间
{
int c=0,n=0;
int *x=NULL;
Knap<int> *bag=NULL;
int cp=0,cw=0;
int bestp=0;
}
using namespace jie;
#include<cstdio>
#include<conio.h>
#include<iomanip>
using namespace std;
template<class ty>
class Knap
{
public:
friend void Init();
friend void Knapsack();
friend void Backtrack(int i);
实验4回溯法解0-1背包问题
一、实验要求
1.要求用回溯法求解0-1背包问题;
2.要求交互输入背包容量,物品重量数组,物品价值数组;
3.要求显示结果。
二、实验仪器和软件平台
仪器:带usb接口微机
软件平台:WIN-XP +VC++6.0
三、实验源码
#include "stdafx.h"
#include<iostream>
int flag; //记录是否放入包中
};
template<class ty>
void Sort(Knap<ty> *li,int n)
{
int i,j,k;Knap<ty> minl;
for(i=1;i<n;i++)
{
minl=li[0];k=0;
for(j=1;j<=n-i;j++)
{
if(minl<li[j])
Init();
Backtrack(0);
Knapsack();
return 0;
}
四、运行结果
五、实验小结
通过该实验,我充分了解了回溯法与分支界限法的区别。回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
friend float Bound(int i);
bool operator<(Knap<ty> a)const
{
if(fl<a.fl)return true;
elsereturn false;
}
private:
ty w; //重量
ty v; //价值
float fl; //单位重量的价值v/w
int kk; //记录第几个物品
}
if(Bound(i+1)>bestp)//进入右子树
{
bag[i].flag=0;Backtrack(i+1);
}
}
//计算当前节点处的上界
float Bound(int i)
{
int cleft = c-cw; //剩余容量
float b = cp;
while (i<n&&bag[i].w<=cleft)
for(int i=1;i<=n;i++)
{
cout<<x[i-1];
}
delete []bag;bag=NULL;
delete []x;x=NULL;
cout<<endl;getch();
}
int main()
{
cout<<endl;
cout<<"|**********回溯法解0-1背包问题**********|"<<endl;
{
//以物品单位重量价值递减序装入
cleft-=bag[i].w ;
b+=bag[i].v;
i++;Leabharlann Baidu
}
//装满背包
if (i<n) b+=1.0*bag[i].v/bag[i].w * cleft;
return b;
}
void Knapsack() //计算最优解和变量值
{
int L(0); //用L累计价值,初始价值设置为0
}
}
void Backtrack(int i)
{
if(i>=n) //到达叶节点
{
bestp=cp; //更新最优价值
return;
}
if(cw+bag[i].w<=c) //进入左子树
{
bag[i].flag=1;cw+=bag[i].w;
cp+=bag[i].v;Backtrack(i+1);
cw-=bag[i].w;cp-=bag[i].v;
void Init()
{
int i=0;
cout<<endl;
cout<<"请输入物品数量n = ";
cin>>n;cout<<endl;
cout<<"请输入背包容量C = ";
cin>>c;cout<<endl;
bag=new Knap<int> [n];
x=new int[n];
cout<<"请依次输入"<<n<<"个物品的重量W:"<<endl;
cin>>bag[i].w;
cout<<endl;
cout<<"请依次输入"<<n<<"个物品的价值P:"<<endl;
for(i=0;i<n;i++)
cin>>bag[i].v;
for(i=0;i<n;i++)
{
bag[i].flag=0;bag[i].kk=i;
bag[i].fl=1.0*bag[i].v/bag[i].w;
for(int k=0;k<n;k++)
{
x[bag[k].kk]=bag[k].flag; //x=0表示未放入背包,x=1表示放入背包
L+=bag[k].flag*bag[k].v; //价值累加
}
cout<<endl;
cout<<"当前最优价值为:"<<L<<endl;
cout<<"变量值x = ";
{
minl=li[j];swap(li[j],li[k]);k=j;
}
}
}
}
namespace jie //命名空间
{
int c=0,n=0;
int *x=NULL;
Knap<int> *bag=NULL;
int cp=0,cw=0;
int bestp=0;
}
using namespace jie;
#include<cstdio>
#include<conio.h>
#include<iomanip>
using namespace std;
template<class ty>
class Knap
{
public:
friend void Init();
friend void Knapsack();
friend void Backtrack(int i);
实验4回溯法解0-1背包问题
一、实验要求
1.要求用回溯法求解0-1背包问题;
2.要求交互输入背包容量,物品重量数组,物品价值数组;
3.要求显示结果。
二、实验仪器和软件平台
仪器:带usb接口微机
软件平台:WIN-XP +VC++6.0
三、实验源码
#include "stdafx.h"
#include<iostream>
int flag; //记录是否放入包中
};
template<class ty>
void Sort(Knap<ty> *li,int n)
{
int i,j,k;Knap<ty> minl;
for(i=1;i<n;i++)
{
minl=li[0];k=0;
for(j=1;j<=n-i;j++)
{
if(minl<li[j])
Init();
Backtrack(0);
Knapsack();
return 0;
}
四、运行结果
五、实验小结
通过该实验,我充分了解了回溯法与分支界限法的区别。回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
friend float Bound(int i);
bool operator<(Knap<ty> a)const
{
if(fl<a.fl)return true;
elsereturn false;
}
private:
ty w; //重量
ty v; //价值
float fl; //单位重量的价值v/w
int kk; //记录第几个物品
}
if(Bound(i+1)>bestp)//进入右子树
{
bag[i].flag=0;Backtrack(i+1);
}
}
//计算当前节点处的上界
float Bound(int i)
{
int cleft = c-cw; //剩余容量
float b = cp;
while (i<n&&bag[i].w<=cleft)
for(int i=1;i<=n;i++)
{
cout<<x[i-1];
}
delete []bag;bag=NULL;
delete []x;x=NULL;
cout<<endl;getch();
}
int main()
{
cout<<endl;
cout<<"|**********回溯法解0-1背包问题**********|"<<endl;
{
//以物品单位重量价值递减序装入
cleft-=bag[i].w ;
b+=bag[i].v;
i++;Leabharlann Baidu
}
//装满背包
if (i<n) b+=1.0*bag[i].v/bag[i].w * cleft;
return b;
}
void Knapsack() //计算最优解和变量值
{
int L(0); //用L累计价值,初始价值设置为0
}
}
void Backtrack(int i)
{
if(i>=n) //到达叶节点
{
bestp=cp; //更新最优价值
return;
}
if(cw+bag[i].w<=c) //进入左子树
{
bag[i].flag=1;cw+=bag[i].w;
cp+=bag[i].v;Backtrack(i+1);
cw-=bag[i].w;cp-=bag[i].v;
void Init()
{
int i=0;
cout<<endl;
cout<<"请输入物品数量n = ";
cin>>n;cout<<endl;
cout<<"请输入背包容量C = ";
cin>>c;cout<<endl;
bag=new Knap<int> [n];
x=new int[n];
cout<<"请依次输入"<<n<<"个物品的重量W:"<<endl;