二維背包問題


二維背包問題

 一 問題描述:

  二維費用的背包問題是指:
  對於每件物品,具有兩種不同的費用;
  選擇這件物品必須同時付出這兩種代價;對於每種代價都有一個可付出的最大值(背包容量)。
  問怎樣選擇物品可以得到最大的價值。設這兩種代價分別為代價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; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM