zoukankan      html  css  js  c++  java
  • 背包问题

    acm入门算法--简单背包问题


    01背包问题
    问题描述:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。


    0-1背包问题


    Time Limit: 1 Second(s)    Memory Limit: 32 MB
    Total Submission(s): 1172   Accepted Submission(s): 456

    Problem Description
     
    给定n种物品和1个背包,物品i的重量是wi,其价值为vi,背包的容量为C。要求选择装入背包的物品,使得装入背包中物品的总价值最大。

    Input

    每组测试数据包含3行,第1行为n和c,表示有n(0<=n<=400)个物品且背包容量为c (c<=1500),第二行为这n个物品的重量wi(1<=wi<=1000),第三行为这n个物品的价值vi。背包容量和物品重量都为整数。

    Output

    输出装入背包的最大总价值,每个答案一行。

    Sample Input

    5 10
    2 2 6 5 4
    6 3 5 4 6

    Sample Output

    15

    算法思想:背包问题是典型的动态规划问题,给定一个背包和这个背包的承重量,怎么放才能使背包实现物品的最大价值。

    01背包问题的特点是:每种物品仅有一件,可以选择放或不放。(所以说是最基础的,后面还会有完全背包,多重背包,就不局限在一件,也可以有更多选择)。

    接下来我们来确认状态转移方程:

    每一件物品都有两种选择,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果第i件物品重量不超过背包的承重量(超重肯定不能放),

    我们选择不把第i件物品放入背包中,此时背包实现的最大价值就等同于前i-1件物品在同等容量背包中实现的最大价值f[i-1][c];

    如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为c-w[i]的背包中”,此时能获得的最大价值就是f [i-1][c-w[i]]再加上通过放入第i件物品获得的价值v[i]。

    设f[i][j]为第i件物品放入背包容量为j的背包中实现的最大价值,不难得出状态转移方程为:

    f[i][j]=max{f[i-1][c], f[i-1][c-w[i]]+v[i]}

    下面贴出代码:

     #include<iostream.h>
    #include<string.h>
    int f[402][1502],w[402],v[402];
    
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    
    int KnapSack(int n,int c,int w[],int v[])
    {
        int i,j;
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=c;j++)
            {
                if(j<w[i-1])//物品重量超过背包容量
                    f[i][j]=f[i-1][j];
                else//选择放或不放的最优策略
                    f[i][j]=max(f[i-1][j],f[i-1][j-w[i-1]]+v[i-1]);
            }
        }
        return f[n][c];
    }
    
    int main()
    {
        int n,c;
        while(cin>>n>>c)
        {
            int i;
            for(i=0;i<n;i++) cin>>w[i];
            for(i=0;i<n;i++) cin>>v[i];
            int maxv=KnapSack(n,c,w,v);
            cout<<maxv<<endl;
        }
    
        return 0;
    }
    

     二维背包问题

    问题描述:大体与01背包相似,只是多了个限制条件,01背包会了,这个也不难

    二维费用背包问题

    Time Limit: 1 Second(s)    Memory Limit: 32 MB
    Total Submission(s): 91   Accepted Submission(s): 49

    Problem Description
     
    给定N种物品和1个背包,物品i的体积是ai,重量是bi, 价值为vi,背包的体积为V,背包的最大承载重量W。要求选择装入背包的物品,使得装入背包中物品的总价值最大。

    Input

    每组测试数据包含4行,第1行为N,V,W,表示有N个物品且背包体积为V和载重量W,第2行为这N个物品的体积ai,第3行为这N个物品的重量bi,第4行为这N个物品的价值vi。

    所有输入数字都为整数,范围大于0,小于等于100。处理到文件结束。

    Output

    输出装入背包的最大总价值,每个答案一行。

    Sample Input

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

    Sample Output

    3

    算法思想:状态转移方程同01背包类似,多了体积这个限制,如果第i件物品放入背包中问题就转化为“前i-1件物品放入剩下的承重量为c-w[i],体积为v-a[i]的背包”,

    此时能获得的最大价值就是f [i-1][c-w[i]][v-a[i]]再加上通过放入第i件物品获得的价值v[i]。

    设f[i][j][k]为第i件物品放入背包容量为j,体积为k的背包中实现的最大价值,不难得出状态转移方程为:

    f[i][j][k]=max{f[i-1][c][v], f[i-1][c-w[i]][v-a[i]]+v[i]}

    代码如下:

    #include<iostream>
    #include<string>
    using namespace std;
    int a[100],v[100],w[100],f[100][100][100];
     
    int maxV(int v1,int v2){
        return v1>v2?v1:v2;
    }
     
    int main(){
        int N,V,W;
        while(cin>>N>>V>>W){
             
         
        int i,j,k;
        memset(f,0,sizeof(f));
        for(i=0;i<N;i++)cin>>a[i];
        for(i=0;i<N;i++)cin>>w[i];
        for(i=0;i<N;i++)cin>>v[i];
        for(i=0;i<N;i++){
            for(j=0;j<=V;j++){
                for(k=0;k<=W;k++){
                    if(i==0){//第一件物品
                        if(a[i]<=j&&w[i]<=k)//满足背包条件限制
                            f[i][j][k]=v[i];//最大实现价值为当前物品价值
                    }
                    else{
                         
                        if(a[i]>j||w[i]>k)
                            f[i][j][k]=f[i-1][j][k];
                        else
                            f[i][j][k]=maxV(f[i-1][j][k],f[i-1][j-a[i]][k-w[i]]+v[i]);
                    }
                }
            }
        }
     
         
        cout<<f[N-1][V][W]<<endl;
        }
        return 0;
    }
    

     

     

  • 相关阅读:
    UVA 12657 Boxes in a Line 双向链表模拟
    C语言单片和C#语言服务器端DES及3DES加密的实现
    关于TcpClient,Socket连接超时的几种处理方法
    拿来参考的学习计划
    faire la course
    今日法语2
    炸鱼
    今日法语
    今日疑问
    下周想做的菜
  • 原文地址:https://www.cnblogs.com/wengXiaofeng/p/6771108.html
Copyright © 2011-2022 走看看