二維揹包問題
有N件物品和一個容量爲V,載重爲U的揹包。第i件物品的體積是a[i],重量是b[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大java
二維費用的揹包問題是指:對於每件物品,具備兩種不一樣的費用;選擇這件物品必須同時付出這兩種代價;對於每種代價都有一個可付出的最大值(揹包容量)。問怎樣選擇物品能夠獲得最大的價值。設這兩種代價分別爲代價1和代價2,第i件物品所需的兩種代價分別爲a[i]和b[i]。兩種代價可付出的最大值(兩種揹包容量)分別爲V和U。物品的價值爲w[i]。數組
費用加了一維,只需狀態也加一維便可。設f[i][v][u]表示前i件物品付出兩種代價分別爲v和u時可得到的最大價值。狀態轉移方程就是:f [i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}。如前述方法,能夠只使用二維的數組:當每件物品只能夠取一次時變量v和u採用逆序的循環,當物品有如徹底揹包問題時採用順序的循環。當物品有如多重揹包問題時拆分物品。spa
物品總個數的限制
有時,「二維費用」的條件是以這樣一種隱含的方式給出的:最多隻能取M件物品。這事實上至關於每件物品多了一種「件數」的費用,每一個物品的件數費用均爲1,能夠付出的最大件數費用爲M。換句話說,設f[v][m]表示付出費用v、最多選m件時可獲得的最大價值,則根據物品的類型(0一、徹底、多重)用不一樣的方法循環更新,最後在f[0..V][0..M]範圍內尋找答案。code
第一種,二維揹包和01揹包blog
import java.util.*; //這是二維揹包和01揹包結合的狀況 public class Main1 { static int INF=-10000; public static int beibao(int f[][],int w[],int a[],int b[],int U,int V,int T){ for(int i=1;i<=U;i++) for(int j=1;j<=V;j++) f[i][j]=INF; f[0][0]=0; for(int i=0;i<T;i++){ for(int j=U;j>=a[i];j--){ for(int k=V;k>=b[i];k--){ f[j][k]=Math.max(f[j-a[i]][k-b[i]]+w[i],f[j][k]); } } } return f[U][V]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int U = 1000; int V = 1000; int T =5; int f[][]=new int[U+1][V+1]; int w[] = {8 , 10 , 4 , 5 , 5}; //價值 int a[] = {600 , 400 , 200 , 200 , 300}; //每個的體積 int b[] = {800 , 400 , 200 , 200 , 300}; int t = beibao(f, w, a, b, U, V, T); System.out.println(t); } }
第二種:杭電2159 二維揹包加徹底揹包:get
import java.util.*; public class Main1{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); int m = sc.nextInt(); int k = sc.nextInt(); int s = sc.nextInt(); int a[]=new int[k+1]; int b[]=new int[k+1]; int dp[][]=new int[s+1][m+1]; for(int i=0;i<k;i++){ a[i]=sc.nextInt(); b[i]=sc.nextInt(); } for(int i=0;i<k;i++) for(int j=1;j<=s;j++) for(int l=b[i];l<=m;l++) dp[j][l]=Math.max(dp[j][l],dp[j-1][l-b[i]]+a[i]); if(dp[s][m]>=n){ for(int i=0;i<=m;i++){ if(dp[s][i]>=n) { System.out.println(m-i); break; } } } else System.out.println(-1); } } }