0-1背包问题

0-1背包问题

时限:1000ms 内存限制:10000K  总时限:3000ms

描述
需对容量为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
对于0-1背包问题来说,贪婪的策略有常用的四种。每种贪婪策略都采用多步过程来完成背包的装入。在每一步过程中利用贪婪准则选择一个物品装入背包。
   一种贪婪准则为:从剩余的物品中,选出可以装入背包的价值最大的物品,利用这种规则,价值最大的物品首先被装入(假设有足够容量),然后是下一个价值最大的物品,如此继续下去。这种策略不能保证得到最优解。
  第二种准则从剩下的物品中选择可装入背包的重量最小的物品,如此继续下去直到不能满足条件为止。在一般情况下不一定能得到最优解。
  第三种是价值密度(价值重量比Pi/Wi)贪婪算法,这种选择准则为:从剩余物品中选择可装入包的Pi/Wi值最大的物品。这种策略也不能保证得到最优解。
  第四种则为启发式贪婪算法。
下面的代码采用贪心策略一:
#include <iostream>
using namespace std;
 
typedef struct mine{
     int weight;             //物品的重量
     int price;              //物品的价值
} mine;
 
int main()
{
    int num,container;
    mine data[25];
    cin>>num>>container;
    while(true)
    {
        if(num==0&&container==0)
        break;
        for(int i = 0;i < num; i++)
            cin>>data[i].weight;
        for(i = 0;i < num; i++)                                                 
            cin>>data[i].price;

        for(int m = 0;m < num-1; m++)                               //将物品按价值排序
            for(int n = 0;n < num-m-1; n++)
                if(data[n].price<data[n+1].price)
                {
                    mine temp;
                    temp.price = data[n].price;
                    temp.weight = data[n].weight;
                    data[n].price = data[n+1].price;
                    data[n].weight = data[n+1].weight;
                    data[n+1].price = temp.price;
                    data[n+1].weight = temp.weight;
                }
        int sumweight = 0;
        int sumprice = 0;
        for(int k = 0;k < num; k++)
            if(data[k].weight<=(container-sumweight))
             {
                 sumprice += data[k].price;
                 sumweight += data[k].weight;
             }
        
        cout<<sumprice<<endl;
        
        cin>>num>>container;
    }
    return 0;
}

 并不可以保证得到最优解,例如:

输入:

10 100

4 5 6 6 7 7 8 9 11 45

7 9 11 12 13 14 15 17 21 89

输出为192

采用动态规划算法:

#include <iostream>

using namespace std;

int main()
{
    int n,c,i,j;
    cin>>n>>c;
    while(n!=0||c!=0)
    {
        int *w =new int[n];
        int *p =new int[n];
        int **a = new int*[n+1];
        for(i=0;i<=n;i++)
           a[i]= new int[c+1];
        for(i=0;i<n;i++)
          cin>>w[i];
        for(j=0;j<n;j++)
          cin>>p[j];
        for(int k=0;k<c+1;k++)
          a[0][k] = 0;
        for(i=0;i<n;i++)
            for(j=0;j<=c;j++)
            {
                if(w[i]>j)a[i+1][j] = a[i][j];
                else if(a[i][j]<a[i][j-w[i]]+p[i]) a[i+1][j] = a[i][j-w[i]]+p[i];
                else a[i+1][j] = a[i][j];
            }
        cout<<a[n][c]<<endl;
        cin>>n>>c;
    }
  return 0;
}

 对于上述同样的输入可以得到193,原因在于可以用重量为4和5的物品代替重量为11的物品,从而获得最大的价值。

态度决定高度,细节决定成败,
原文地址:https://www.cnblogs.com/lxk2010012997/p/4390557.html