《算法设计与分析》实验报告六
学号: 1004091130 | | 姓名: 金玉琦 |
日期: 2011-11-17 | | 得分: |
| | |
一、实验内容:
二、所用算法的基本思想及复杂度分析:
分支限界法
分支限界法按广度优先策略遍历问题的解空间树, 在遍历过程中, 对已经处理的每一个结点根据限界函数估算目标函数的可能取值, 从中选取使目标函数取得极值 的结点优先进行广度优先搜索, 从而不断调整搜索方向, 尽快到问题的解。因为限界函数常常是基于问题的目标函数而确定的, 所以, 分支限界法适用于求解最优化问题。 0-1背包问题
1)基本思想
给定n 种物品和一个容量为C 的背包, 物品i 的重量是Wi, 其价值为Vi , 0/ 1 背包问题是如何选择装入背包的物品(物品不可分割) , 使得装入背包中物品的总价值最大,一般情况下, 解空间树中第i 层的每个结点, 都代表了对物品1~ i 做出的某种特定选择, 这个特定选择由从根结点到该结点的路径唯一确定: 左分支表示装入物品, 右分支表示不装入物品。对于第i 层的某个结点, 假设背包中已装入物品的重量是w, 获得的价值是v, 计算该结点的目标函数上界的一个简单方法是把已经装入背包中的物品取得的价值v, 加上背包剩余容量W - w 与剩下物品的最大单位重量价值vi + 1/ wi + 1的积,于是,得到限界函数: u b = v + ( W - w) × ( vi + 1/ wi + 1 )
根据限界函数确定目标函数的界[ down , up],然后, 按照广度优先策略遍历问题的空 间树。
2)复杂度分析
时间复杂度是O(2n);
三、源程序及注释:
#include<iostream>
#include<cstdio>
#include<conio.h>
#include<iomanip>
using namespace std;
int *x;
struct node
{
//结点表结点数据结构
node *parent,//父结点指针
*next; //后继结点指针
int level,//结点的层
bag,//节点的解
cw,//当前背包装载量
cp;//当前背包价值
float ub; //结点的上界值
};
class Knap
{ebsco
private:
struct node *front, //队列队首
*bestp,*first; //解结点、根结点
int *p,*w,n,c,*M;//背包价值、重量、物品数、背包容量、记录大小顺序关系
long lbestp;//背包容量最优解
public:
void Sort();
Knap(int *pp,int *ww,int cc,int nn);
~Knap();
float Bound(int i,int cw,int cp);//计算上界限
node *nnoder(node *pa,int ba,float uub);//生成一个结点 ba=1生成左节点 ba=0生成右节点
void addnode(node *nod);//将结点添加到队列中
void deletenode(node *nod);//将结点队列中删除
struct node *nextnode(); //取下一个
void display(); //输出结果
void solvebag(); //背包问题求解
};
Knap::Knap(int *pp,int *ww,int cc,int nn)
{
int i;
n=nn;
c=cc;
p=new int[n];
w=new int[n];
M=new int[n];
for(i=0;i<n;i++)
{
p[i]=pp[i];
w[i]=ww[i];
M[i]=i;
}
front=new node[1];
front->next=NULL;
lbestp=0;
bestp=new node[1];
bestp=NULL;
Sort();
}
Knap::~Knap()
{
delete []first;
delete []front;
delete []bestp;
delete []p;
delete []w;
}
float Knap::Bound(int i,int cw,int cp)
{// 计算上界
int cleft=c-cw;
float b=(float)cp;
while (i<n&&w[i]<=cleft)
{
cleft-=w[i];
b+=p[i];
i++;
}
if (i<n) b+=1.0*p[i]/w[i]*cleft;
return b;
}
node * Knap::nnoder(struct node *pa,int ba,float uub)
{//生成一个新结点
node * nodell=new(node);
nodell->parent=pa;
nodell->next=NULL;
nodell->level=(pa->level)+1;
nodell->bag=ba;
nodell->ub=uub;
if(ba==1)
{
nodell->cw=pa->cw+w[pa->level];
nodell->cp=pa->cp+p[pa->level] ;
}
else
{
nodell->cw=pa->cw;
nodell->cp=pa->cp;
}
return(nodell);
}
void Knap::addnode(node *no)
{//将结点加入优先队列
node *p=front->next,*next1=front;
float ub=no->ub;
while(p!=NULL)
{
if(p->ub<ub)
{no->next=p;next1->next=no;break;}
next1=p;
p=p->next;
}
if(p==NULL){next1->next=no;
}
}
node *Knap::nextnode()
{//取上限最大结点
node *p=front->next;
front->next=p->next;
return(p);
}
void Knap::Sort()
{
int i,j,k,kkl;
float minl;
for(i=1;i<n;i++)
{
minl=1.0*p[i]/w[i];
k=0;
for(j=1;j<=n-i;j++)
{
条子生 if(minl<1.0*p[j]/w[j])
{
minl=1.0*p[j]/w[j];
姚海星 swap(p[k],p[j]);鱼塘理论
swap(w[k],w[j]);
swap(M[k],M[j]);
k=j;
}
}
}
}
void Knap::display()
{
int i;
cout<<"最大价值是:"<<lbestp<<endl;
for(i=n;i>=1;i--)
浙江省人口与计划生育条例
{
x[M[i-1]]=bestp->bag;
bestp=bestp->parent;
}
cout<<"变量值为:"<<endl;
for(i=1;i<=n;i++)
cout<<"x("<<setw(2)<<i<<")="<<x[i-1]<<endl;
}
void Knap::solvebag()
{//背包问题求解
int i;
float ubb;
node *aa;
first=new node[1]; //根结点
first->parent=NULL;
first->next=NULL;
first->level=0;
>托姆布雷