0-1背包(回溯法)

描述:

需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。

输入:

多个测例,每个测例的输入占三行。第一行两个整数:n(n<=10)和c,第二行n个整数分别是w1到wn,第三行n个整数分别是p1到pn。
n 和 c 都等于零标志输入结束。

输出:

每个测例的输出占一行,输出一个整数,即最佳装载的总价值。

输入样例:

1 2 1 1 2 3 2 2 3 4 0 0

输出样例:

1 4

 

#include <iostream>
#include <algorithm>
using namespace std;

double c;       //背包容量
int n;          //物品数
double cw;      //当前重量
double cp;      //当前价值
int bestp;   //当前最优价值
typedef struct Item
{
    double w;   //物品的重量
    double p;   //物品的价值
}Item;
Item item[100];

bool cmp(Item a, Item b)
{
    return a.p/a.w > b.p/b.w;
}
double bound(int i)
{
    double cleft = c - cw;     //剩余容量
    double b = cp;             //能装载容量的最大上界

    //将剩余物品装入背包,直至装不下为止
    while(i <= n && item[i].w <= cleft)
    {
        cleft -= item[i].w;
        b += item[i].p;
    }
    //将最后一件装不下的物品拆解,让背包装满
    //计算能装载容量的最大上界
    if(i <= n)
        b += item[i].p/item[i].w*cleft;
    return b;
}
void Backtrack(int i)
{
    //叶子节点
    if(i > n)
    {
        if(cp > bestp)              //上界不一定取到            
            bestp = (int)cp;        
        //cout << "bestp " << bestp << endl;
        return;
    }

    //搜索子树
    if(cw + item[i].w <= c)
    {
        cw += item[i].w;
        cp += item[i].p;
        //cout <<"cw =" << cw <<"cp ="<< cp << endl;
        Backtrack(i+1);

        cw -= item[i].w;
        cp -= item[i].p;
        //cout <<"cw =" << cw <<"cp ="<< cp << endl;
    }
    if(bound(i+1) > bestp)
        Backtrack(i+1);
}


int main()
{
    while(cin >> n >> c && (n || c))
    {
        bestp = 0;                      //每组样例初始化
        for(int i = 1; i <= n; i ++)    //i从1开始
            cin >> item[i].w;
        for(int i = 1; i <= n; i ++)
            cin >> item[i].p;
        sort(item+1, item+n+1, cmp);    //从1开始,wa了好多次

        Backtrack(1);                  //从1开始递归
        printf("%d\n", bestp);
    }
    return 0;
}

 

    原文作者:回溯法
    原文地址: https://blog.csdn.net/axiqia/article/details/51038188
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞