0-1背包-分支限界
时间:2022-04-22
本文章向大家介绍0-1背包-分支限界,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
算法描述:
活结点优先队列中结点元素N的优先级由该结点的上界函数Bound计算出的值uprofit给出。
子集树中以结点N为根的子树中任一结点的价值不超过N.profit。
可用一个最大堆来实现或节点优先队列。
N.weight 是结点N所相应的重量,N.profit是N所相应的价值,N.uprofit是结点N的价值上界,最大堆以这个值作为优先级。
class Object{
friend int Knapsack(int *,int *,int ,int ,int *);
public:
int operator <= (Object a) const
{
return (d >= a.d);
}
private:
int ID;
float d;
};
template <class Typew,class Typep>
class Knap;
class bbnode{
friend Knap<int,int>;
friend int Knapsack(int *,int *,int,int,int *);
private:
bbnode * parent;
bool LChild;
};
template <class Typew,class Typep>
class HeapNode{
friend Knap<Typew,Typep>;
public:
operator Typep() const
{
return uprofit;
}
private:
Typep uprofit,//结点价值上界
profit;
Typew weight;
int level;//活结点所相应的重量
bbnode * ptr;
};
上界计算函数:
template <class Typew,class Typep>
class Knap<Typew,Typep>::Bound(int i)
{
Typew cleft = c- cw;//剩余容量
Typep b = cp;//价值上界
//以物品单位重量价值递减序装填剩余容量
while(i<=n && w[i] <= cleft)
{
cleft -= w[i];
b += p[i];
i++;
}
//装填剩余容量装满背包
if(i<=n)
b += p[i]/w[i] * cleft;
return b;
}
分支限界搜索函数:
template <class Typew,class Typep>
Typep Knap<Typew,Typep>::MaxKnapsack()
{
//优先队列式分支限界法,返回最大价值,bestx返回最优解
//定义最大堆的容量为1000
H = new MaxHeap< HeapNode<Typew,Typep> >(1000);
//为bestx分配存储空间
bestx = new int [n+1];
//初始化
int i=1;
E= 0;
cw = cp = 0;
Typep bestp = 0;
Typep up = Bound(1);
//搜索子集空间树
while(i!=n+1)//非叶节点
{
//检查当前扩展结点的左儿子结点
Typew wt = cw + w[i];
if(wt <= c)
{
if(cp+p[i] > bestp)
bestp = cp+p[i];
AddLiveNode(up,cp+p[i],cw+w[i],true,i+1);
}
up = Bound(i+1);
//检查扩展结点的右儿子结点
if(up >= bestp)//右子树 可能含有最优解
AddLiveNode(up,cp,cw,false,i+1);
//取得下一扩展点
HeapNode<Typep,Typew> N;
H->DeleteMax(N);
E = N.ptr;
cw = N.weight;
cp = N.profit;
up = N.uprofit;
i = N.level;
}
//构造当前最优解
for(int j=n;j>0;j--)
{
bestx[j] = E->LChild;
E = E->parent;
}
return cp;
}
主要程序代码:
测试中.....(暂时不好使)
#include <iostream>
#include <algorithm>
class Object{
friend int Knapsack(int *,int *,int ,int ,int *);
public:
int operator <= (Object a) const
{
return (d >= a.d);
}
private:
int ID;
float d;
};
template <class Typew,class Typep>
class Knap;
class bbnode{
friend Knap<int,int>;
friend int Knapsack(int *,int *,int,int,int *);
private:
bbnode * parent;
bool LChild;
};
template <class Typew,class Typep>
class HeapNode{
friend Knap<Typew,Typep>;
public:
operator Typep() const
{
return uprofit;
}
private:
Typep uprofit,//结点价值上界
profit;
Typew weight;
int level;//活结点所相应的重量
bbnode * ptr;
};
template <class Typew,class Typep>
class Knap{
friend Typep Knapsack(Typep *,Typew *,Typew ,int ,int *);
public:
Typep MaxKnapsack();
private:
MaxHeap<HeapNode<Typep,Typew> > * H;
Typep Bound(int i);
void AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int level);
bbnode * E;
Typew c;
int n;
Typew * w;
Typep *p;
Typew cw;
Typep cp;
int *bestx;
};
template <class Typew,class Typep>
class Knap<Typew,Typep>::Bound(int i)
{
Typew cleft = c- cw;//剩余容量
Typep b = cp;//价值上界
//以物品单位重量价值递减序装填剩余容量
while(i<=n && w[i] <= cleft)
{
cleft -= w[i];
b += p[i];
i++;
}
//装填剩余容量装满背包
if(i<=n)
b += p[i]/w[i] * cleft;
return b;
}
template <class Typep,class Typew>
void Knap<Typep,Typew>::AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int lev)
{
//将一个新的活结点插入到子集树 和 最大堆 H中
bbnode *b = new bbnode;
b->parent = E;
b->LChild = ch;
HeapNode<Typep,Typew> N;
N.uprofit = up;
N.profit = cp;
N.weight = cw;
N.level = lev;
N.ptr = b;
H->Insert(N);
}
template <class Typew,class Typep>
Typep Knap<Typew,Typep>::MaxKnapsack()
{
//优先队列式分支限界法,返回最大价值,bestx返回最优解
//定义最大堆的容量为1000
H = new MaxHeap< HeapNode<Typew,Typep> >(1000);
//为bestx分配存储空间
bestx = new int [n+1];
//初始化
int i=1;
E= 0;
cw = cp = 0;
Typep bestp = 0;
Typep up = Bound(1);
//搜索子集空间树
while(i!=n+1)//非叶节点
{
//检查当前扩展结点的左儿子结点
Typew wt = cw + w[i];
if(wt <= c)
{
if(cp+p[i] > bestp)
bestp = cp+p[i];
AddLiveNode(up,cp+p[i],cw+w[i],true,i+1);
}
up = Bound(i+1);
//检查扩展结点的右儿子结点
if(up >= bestp)//右子树 可能含有最优解
AddLiveNode(up,cp,cw,false,i+1);
//取得下一扩展点
HeapNode<Typep,Typew> N;
H->DeleteMax(N);
E = N.ptr;
cw = N.weight;
cp = N.profit;
up = N.uprofit;
i = N.level;
}
//构造当前最优解
for(int j=n;j>0;j--)
{
bestx[j] = E->LChild;
E = E->parent;
}
return cp;
}
template <class Typew,class Typep>
Typep Knapsack(Typep p[],Typew w[],Typew c,int n,int bestx[])
{
Typew W = 0;
Typep P = 0;
//按 单位重量价值 排序
Object * Q = new Object [n];
for(int i=1;i<=n;i++)
{
Q[i-1].ID = i;
Q[i-1].d = 1.0*p[i]/w[i];
P += p[i];
W += w[i];
}
if(W<=c)
return P;
Sort(Q,n);
Knap<Typew,Typep> K;
K.p = new Typep[n+1];
K.w = new Typew[n+1];
for(int i=1;i<=n;i++)
{
K.p[i] = p[Q[i-1].ID];
K.w[i] = p[Q[i-1].ID];
}
K.cp = 0;
K.cw = 0;
K.c = c;
K.n = n;
Typep bestp = K.MaxKnapsack();
for(int j=1;j<=n;j++)
{
bestx[Q[i-1].ID] = K.bestx[j];
cout<<bestx[Q[i-1.ID]]<<endl;
}
delete [] Q;
delete [] K.w;
delete [] K.p;
delete [] K.bestx;
cout<<"最大价值为"<<bestp<<endl;
return bestp;
}
int main()
{
int n,m;
int w[100],p[100],best[100];
cout<<"请输入想要输入的物品个数 及 背包重量:"<<endl;
cin>>n>>m;
cout<<"请依次输入想要输入的物品重量 及 价值"<<endl;
for(int i=0;i<n;i++)
cin>>w[i]>>p[i];
Knapsack(w,p,m,n,best);
return 0;
}
- [C#1] 6-方法
- 如何删除WordPress 的“多站点”模式(multisite)?
- 部分Sonos及Bose扬声器爆安全漏洞,被黑客入侵后发出特定音频
- TCP - WAIT状态及其对繁忙的服务器的影响
- 在Windows 7/Server 2008 R2上部署asp.net 1.1程序
- CSS Auto Reload:解放F5 键,自动刷新浏览器的前端利器(Chrome 扩展)
- zepto 基础知识(3)
- 1.[Andriod]之Andriod布局 VS WinPhone布局
- WordPress自定义url 中的“author” 别名
- ASP.NET 4 AppFabric 输出缓存提供程序
- WordPress 中禁止编辑“已发布”的文章
- Windows Server 2008 R2 网络负载平衡 (NLB)资料汇总
- 0.[Andriod]之从零安装配置Android Studio并编写第一个Android App
- WordPress 后台编辑文章页面添加自定义提示文字
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 多个Laravel项目如何共用migrations详解
- PHP实现文字写入图片功能
- php中file_get_contents()函数用法实例
- PHP通过GD库实现验证码功能示例
- Thinkphp 5.0实现微信企业付款到零钱
- 使用npy转image图像并保存的实例
- php实现有序数组旋转后寻找最小值方法
- 基于python实现音乐播放器代码实例
- PHP实现微信对账单处理
- Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
- PHP Include文件实例讲解
- ThinkPHP5.1框架页面跳转及修改跳转页面模版示例
- Python Switch Case三种实现方法代码实例
- PHP正则表达式笔记与实例详解
- php实现微信分享朋友链接功能