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

    二维背包问题

     一 问题描述:

      二维费用的背包问题是指:
      对于每件物品,具有两种不同的费用;
      选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。
      问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,
      第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最大值(两种背包容量)分别为V和U。物品的价值为w[i]。

      f[i][u][v] = max(f[i-1][u][v] , w[i] + f[i-1][u-a[i]][v-b[i]])
      二 加深
      同样的解决二维费用背包的只需要增加一维数组即可,即建立f[u][v]数组
      当为完全背包时候,uv正序,当为01背包的时候uv倒序。
      当存在多重背包问题的时候,就需要将多重背包转换为01背包的情况。

     三 源代码分析

    #include <iostream>
     using namespace std ; 
     const  int V = 1000 ;  //总成本b 
     const  int U = 1000 ;  //总成本a 
     const  int T = 5 ;    //物品的种类 
     
     int f[U+1][V+1] ;                                    //可以不装满 
     int w[T] = {8 , 10 , 4 , 5 , 5};                      //价值 
     int a[T] = {600 , 400 , 200 , 200 , 300};             //每一个的体积 
     int b[T] = {800 , 400 , 200 , 200 , 300};
     const int INF = -66536  ;
       
     int package()
     {
        for(int i = 1 ; i <= U ;i++) //条件编译,表示背包可以不存储满
          for(int j = 1 ; j <= V ;j++)
          f[i][j] = INF ;    
          
          f[0][0] = 0 ; //01
        
        for(int i = 0 ; i < T ; i++)
        {
          for(int u = U ; u >= a[i] ;u--) //必须全部从V递减到0
             {         
               for(int v = V ; v >= b[i] ;v--)                           
                  f[u][v] = max(f[u-a[i]][v-b[i]] + w[i] , f[u][v])  ; //此f[v]实质上是表示的是i-1次之前的值。
             }                 
        }
        return f[U][V] ;        
     }
     
     int main()
     {
          
       int temp = package() ;   
       cout<<temp<<endl     ;   
       system("pause")      ;
       return 0 ;    
     } 

    杭电2159 二维背包加完全背包:

    FATE

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 3943    Accepted Submission(s): 1741


    Problem Description
    最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?
     

     

    Input
    输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)
     

     

    Output
    输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。
     

     

    Sample Input
    10 10 1 10 1 1 10 10 1 9 1 1 9 10 2 10 1 1 2 2
     

     

    Sample Output
    0 -1 1
    本题是求经验值的最大值,在最大值大于升级的最大值时,在判断何时就已经可以升级了,此时求出所要付出的忍耐值!!
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        int i,j,n,m,f[120][120],s,k,a[120],b[120],z;
        while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF)
        {
            memset(f,0,sizeof(f));
            for(i=0;i<k;i++)
                scanf("%d%d",&a[i],&b[i]);
            for(i=0;i<k;i++)
                for(j=1;j<=s;j++)//注意动物的开始数是1
                    for(z=b[i];z<=m;z++)
                        f[j][z]=f[j][z]>(f[j-1][z-b[i]]+a[i])?f[j][z]:(f[j-1][z-b[i]]+a[i]);//注意要j-1
           if(f[s][m]>=n)
            {
                for(i=0;i<=m;++i)
                    if(f[s][i]>=n)
                    {
                        printf("%d\n",m-i);
                        break;
                    }
            }
            else
                printf("-1\n");
          }
        return 0;
    }

     

  • 相关阅读:
    斐波那契数列
    进制转换
    求最大公约数伪代码
    2020-2021-1 20201315 《信息安全专业导论》第5周学习总结
    XOR加密
    pep9线下作业
    2020-2021-1 20201226 《信息安全专业导论》第四周学习总结
    内网与外网
    打开word文档时,出现office更新,并且更新报错
    由于找不到mfc100u.dll,无法继续执行代码
  • 原文地址:https://www.cnblogs.com/xiaofanke/p/2651290.html
Copyright © 2011-2022 走看看