多重背包
有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值 是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大
母函数的思想也是如此 给你 价值, 物品数量的限制, 然后凑,
hdu2191
第一种写法
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); int m = sc.nextInt(); int v[] = new int[101]; int w[] = new int[101]; int num[] = new int[101]; for (int i = 0; i < m; i++) { v[i] = sc.nextInt(); w[i] = sc.nextInt(); num[i] = sc.nextInt(); } int dp[] = new int[10001]; for (int i = 0; i <= m; i++) dp[i] = 0; for (int i = 0; i < m; i++) { for (int k = 0; k <= num[i]; k++) { for (int j = n; j >= v[i]; j--) { if (dp[j] < dp[j - v[i]] + w[i]) { dp[j] = dp[j - v[i]] + w[i]; } } } } System.out.println(dp[n]); } } }
第二种写法:
package demo2; import java.util.*; public class Main { public static int sum(int []n){ int sum=0; for(int i=0;i<n.length;i++) sum+=n[i]; return sum; } public static int back(int []a,int []v,int[]n,int m){ int sum=sum(n); int a1[]= new int[sum]; int v1[]=new int[sum]; for(int i=0;i<a.length;i++) a1[i]=a[i]; for(int i=0;i<v.length;i++) v1[i]=v[i]; int k= a.length; for(int i=0;i<n.length;i++){ while(n[i]!=1){ a1[k]=a[i]; v1[k]=v[i]; k++; n[i]--; } } int dp[]=new int[m+1]; for(int i=0;i<a1.length;i++){ for(int j=m;j>=a1[i];j--){ dp[j] = Math.max(dp[j],dp[j-a1[i]]+v1[i]); } } return dp[m]; } public static void main(String[] args) { int[] a = {1,2,3}; int[] v = {2,1,4}; int[] n = {5,4,2}; int m = 6; int value = back(a,v,n,m); System.out.println(value); } }
优化写法:
将多重背包转换为完全背包
public class duochongbeibao1 { public static int[] a = {1,2,3};//重量 public static int[] v = {2,1,4};//价值 public static int[] n = {5,4,2};//数量 public static int m = 6; public static int back(int[] a,int[] v,int[] n,int m){ int value = fun(a.length-1,m); return value; } public static int fun(int i,int m){ if(i == 0) return(m/a[i]<n[i]?m/a[i]:n[i])*v[i]; else{ int x = (m/a[i]<n[i]?m/a[i]:n[i]) + 1; int[] dp = new int[x]; for(int j = 0;j<x;j++) dp[j] = fun(i-1,m-j*a[i])+j*v[i]; return max(dp); } } public static int max(int[] dp){ int index = 0; if(dp.length == 0) return -1; for(int i = 1;i<dp.length;i++){ if(dp[i]>dp[index]) index = i; } return dp[index]; } public static void main(String[] args) { // TODO Auto-generated method stub int value = back(a,v,n,m); System.out.println(value); } }