n個物品,質量分別wi,價值分別vi,放入包中,包的容量爲T,怎麼放價值最大
最經典的動態規劃的問題,動態規劃不同於貪心算法,貪心算法是通過上一步的最優解求得下一步的最優解,然而很多時候並非最優解,動態規劃是用局部最優解求得全局最優解
揹包的狀態轉換方程 f[i,j] = Max{ f[i-1,j-Wi]+Vi( j >= Wi ), f[i-1,j] }
f[i,j]表示在前i件物品中選擇若干件放在承重爲 j 的揹包中,可以取得的最大價值。Vi表示第i件物品的價值。
說到底是解決第i件物品放不放的問題
如果不放,f[i-1,j]就是前i-1件物品所得到的最大價值,如果放了,f[i-1,j-Wi]+Vi就是在揹包容量減去第i件時前i-1所得到的最大價值加上第i件的價值。
//author:Cenhelm
package hhuc.Dynamicplanning;
import java.util.Random;
/*
* 揹包問題
* 動態規劃
* 轉換方程f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }, f[i,j]表示在前i件物品中選擇若干件放在承重爲 j 的揹包中,可以取得的最大價值。Pi表示第i件物品的價值。
* 沒有遞歸而是放在了‘備忘錄’中
*/
public class Bagproblem {
public int maxvalue(int[] w, int[] v, int t) {
int[][] wv = new int[t+1][w.length];
//容量爲0時總價值都設爲0
for(int i = 0; i < w.length; i++) {
wv[0][i] = 0;
}
for (int i = 1; i <= t; i++) {//i爲1到T
for(int j = 0; j < w.length; j++) {//j是物品ni
if(j == 0) {
if(w[0] <= i) {
wv[i][0] = v[0];
// continue;
}else {
wv[i][0] = 0;
// continue;
}
}
// if(i == 1) {//容量爲1時的價值總量
// for(int k = 1; k < w.length; k++) {
// if(w[k] == 1 && v[k] > v[k-1]) {
// wv[0][k] = v[k];
// }else {
// wv[0][k] = 0;
// }
// }
// }
//
//轉換方程
if(j != 0) {
int wv1 = 0, wv2 = 0;
if(i >= w[j])
wv1 = wv[i-w[j]][j-1] + v[j];
wv2 = wv[i][j-1];
if(wv1 >= wv2)
wv[i][j] = wv1;
else if(wv1 < wv2)
wv[i][j] = wv2;
}
}
}
return wv[t][w.length-1];
}
public static void main(String[] args) {
int[] w = new int[100];// 質量
int[] v = new int[100];// 價值
int T = 1000;// 揹包容量
Random random = new Random();
for (int i = 0; i < w.length; i++) {
w[i] = random.nextInt(100);
System.out.print(w[i] + " ");
}
System.out.println();
for (int i = 0; i < v.length; i++) {
v[i] = random.nextInt(100);
System.out.print(v[i] + " ");
}
Bagproblem bagproblem = new Bagproblem();
System.out.println("\n" + bagproblem.maxvalue(w, v, T));
}
}