回溯法求解0-1背包问题

#include <stdio.h>
#include <stdlib.h>
#define N 5
#define W 10
/*
2 6
2 3
6 5
5 4
4 6
测试用例
*/

void initialization(int *w,int *v,int *x,int *finalx)
{
    int i=0;
    w[0]=0;
    v[0]=0;
    x[0]=0;
    printf("请输入背包的质量和价值:\n");
    for(i=1;i<=N;i++)
    {
        scanf("%d%d",&w[i],&v[i]);
    }
    for(i=1;i<=N;i++)
    {
        x[i]=0;
        finalx[i]=0;
    }

}
void record(int *x,int* finalx)
{
    int i=0;
    for(i=1;i<=N;i++)
    {

        finalx[i]=x[i];
    }
}
void output(int *finalx,int bestp)
{
    int i=0;
    printf("装入背包的方案为:\n将");
    for(i=1;i<=N;i++)
    {
        if(finalx[i]==1)
        {
        printf("%d号  ",i);
        }
    }
     printf("物品装入背包\n");

    printf("装入背包的物品的最大价值是%d\n",bestp);

}
int bound(int i,int cp,int *v,int *p_bestp)
{
    int sum=0;
  while (i <= N )
    {
    sum+=v[i];
    i ++;
    }

	if ((cp+sum)>(*p_bestp))
    {

	return 1;
	}

	else
        {
            return 0;
        }
	}

void backtrack(int t,int *w,int *v,int *x,int cw,int cp,int *p_bestp,int *finalx){
  if (t > N)
    {

     if(cp>*p_bestp)
     {
         *p_bestp=cp;
         record(x,finalx);
     }

     return;
     }
  if (cw + w[t] <= W)
    {
     x[t]=1 ;
     cw += w[t] ;
     cp += v[t] ;
     backtrack(t+1,w,v,x,cw,cp,p_bestp,finalx);
     cw -= w[t];
     cp -= v[t];

    }

  if (bound(t+1,cp,v,p_bestp))
     {
     x[t]=0;
     backtrack(t+1,w,v,x,cw,cp,p_bestp,finalx);
     }
}

int main()
{
    int x[N+1],v[N+1],w[N+1],finalx[N+1],*p_bestp=NULL;
    int bestp=0;
    p_bestp=&bestp;
    initialization(w,v,x,finalx);
    backtrack(1,w,v,x,0,0,p_bestp,finalx);
    output(finalx,bestp);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法解0_1背包问题时,会用到状态空间树。在搜索状态空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索,否则将右子树剪去。设r是当前剩余物品价值总和;cp是当前价值;bestp是当前最优价值。当cp+r≤bestp时,可剪去右子树。计算右子树中解的上界可以用的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界,用此值来剪枝。 为了便于计算上界,可先将物品依其单位重量价值从大到小排序,此后只要顺序考察各物品即可。在实现时,由MaxBoundary函数计算当前结点处的上界。它是类Knap的私有成员。Knap的其他成员记录了解空间树种的节点信息,以减少函数参数的传递以及递归调用时所需要的栈空间。在解空间树的当前扩展结点处,仅当要进入右子树时才计算上界函数MaxBoundary,以判断是否可以将右子树减去。进入左子树时不需要计算上界,因为其上界与父结点的上界相同。 在调用函数Knapsack之前,需要先将各物品依其单位重量价值从达到小排序。为此目的,我们定义了类Objiect。其中,运算符与通常的定义相反,其目的是为了方便调用已有的排序算法。在通常情况下,排序算法将待排序元素从小到大排序。 在搜索状态空间树时,由函数Backtrack控制。在函数中是利用递归调用的方法实现了空间树的搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值