java0-1背包回溯法代码_0-1背包问题回溯法

■回溯法

0-1背包问题是回溯法中的子集选取问题,0-1背包问题的解空间可以用子集树来表示。

设cw为当前重量,w[]为每个物品的重量。在搜索解空间树时,只要其左儿子结点是一个可行结点,即当前重量加该结点的重量小于等于背包容量(cw+w[i]<=c),搜索就进入其左子树。

设上界函数为Bound(int i),当前最优值为bestp。当右子树中有可能包含最优解时才进入右子树搜索。否则将右子树剪去。右子树中有可能包含最优解的条件是右子树的上界大于当前最优值(Bound(i+1)

>bestp)。

计算右子树上界的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下去时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界。排序用到的算法是哨兵算法。

本程序将可选物品定义为一个表来进行运算,比定义数组简洁。

typedef struct{

double p;//物品价值

double w;//物品重量

double v;//物品单位价值

int flag;//物品排序前的位置

}RedType;

typedef struct{

int length;

RedType r[5001];

}SqList;

伪代码如下:

int n;//物品数量

double c;//背包容量

int x[5001]={0};//物品是否放入标志

double bestp=0;//当前最优价值

double cp=0;//当前价值

double cw=0;//当前重量

void sort()

{

…/*利用哨兵法,将物品按单位价值L.r[i].v排序*/

}

int Bound(int i)/*上界函数*/

{

int cleft=c-cw;/*剩余容量*/

while(i<=n&&L.r[i].w<=cleft)/*以物品单位价值递减序装入物品*/

{

cleft-=L.r[i].w;

i++;

}

…/*将背包完全满*/

return;/*返回上界*/

}

void Backtrack(int i)//回溯函数

{

if(i>n)/*到达叶子结点*/

{

bestp=cp;

return;

}

if(cw+L.r[i].w<=c)/*进入左子树*/

{

cw+=L.r[i].w;

cp+=L.r[i].p;

x[i]=1;/*将标记x记为1*/

Backtrack(i+1);

cw-=L.r[i].w;

cp-=L.r[i].p;

}

if(Bound(i+1)>bestp)/*进入右子树*/

Backtrack(i+1);

}

int main()

{

… /*输入数据*/

sort();/*对输入的数据按物品单位价值排序*/

Backtrack(1);/*从第一层开始搜索*/

for(i=1;i<=n;i++) /*输出结果*/

for(j=1;j<=n;j++)

if(L.r[j].flag == i)

{

printf(“%d %d\n”,i,x[j]);

break;

}

printf(“%g\n”,bestp);

}

主程序在输入数据后,调用sort()函数对输入的数据按物品单位价值排序,再调用Backtrack(1)函数从第一层开始递归搜索,最后输入数据。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值