二维背包问题

二维背包问题

 一 问题描述:

  二维费用的背包问题是指:
  对于每件物品,具有两种不同的费用;
  选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。
  问怎样选择物品可以得到最大的价值。设这两种代价分别为代价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;
}

 

原文地址:https://www.cnblogs.com/xiaofanke/p/2651290.html