0-1背包问题(回溯dfs)

题目描述

给定一个物品集合s={1,2,3,…,n},物品i的重量是wi,其价值是vi,背包的容量为W,即最大载重量不超过W。在限定的总重量W内,我们如何选择物品,才能使得物品的总价值最大。

输入

第一个数据是背包的容量为c(1≤c≤1500),第二个数据是物品的数量为n(1≤n≤50)。接下来n行是物品i的重量是wi,其价值为vi。所有的数据全部为整数,且保证输入数据中物品的总重量大于背包的容量。
当c=0时,表示输入数据结束。

输出

对每组测试数据,输出装入背包中物品的最大价值。
在这里插入图片描述

解题思路

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

#include <iostream>
#include<bits/stdc++.h>
#define N 100
#define INF 0x3f3f3f3f
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,n) for(int i=a;i<=n;i++)
typedef long long ll;
using namespace std;
#define NUM 100
int c;//背包的容量
int n;//物品的数量
int cw;//当前重量
int cv;//当前价值
int bestv;//当前最优价值
//描述每个物品的数据结构
struct Object
{
    int w;//物品的重量
    int v;//物品的价值
    double d;//物品的单位重量价值比
}Q[NUM]; //物品的数组
bool cmp(Object a, Object b)
{
    if(a.d>=b.d) return true;//按性价比从大到小
    else return false;
}
//形参i是回溯的深度
int Bound(int i)
{
    int cleft = c-cw;//背包剩余的容量
    int b = cv;//上界
//尽量装满背包
    while(i<n && Q[i].w<=cleft)
    {
        cleft -= Q[i].w;
        b += Q[i].v;
        i++;
    }
//剩余的部分空间也装满
    if (i<n)
        b += 1.0*cleft*Q[i].v/Q[i].w;
    return b;
}
//i从0开始
void backtrack(int i)
{
    //到达叶子结点时,更新最优值
    if (i+1>n)
    {
        bestv = cv;
        return;
    }
    //进入左子树搜索
    if (cw+Q[i].w<=c)
    {
        cw += Q[i].w;
        cv += Q[i].v;
        backtrack(i+1);
        cw -= Q[i].w;
        cv -= Q[i].v;
    }
    //进入右子树搜索
    if (Bound(i+1)>bestv)
        backtrack(i+1);
}
int main()
{
    cin>>c>>n;
    for(int i=0; i<n; i++)
    {
        cin>>Q[i].w>>Q[i].v;
        if(Q[i].w==0)break;
        Q[i].d = 1.0*Q[i].v/Q[i].w;//转换为浮点型再除
    }
    sort(Q,Q+n,cmp);
    backtrack(0);
    cout<<bestv<<endl;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值