题目:
分析:这是一道01背包问题,有一个限制条件就是附件必须要在主件购买的前提下才能购买。本题的总钱数就类似于背包问题中的总重量,价格与重要度乘积的总和就类似于背包问题中的价值。定义数组dp[i][j]表示前i件物品花费j所得到的最大价值,对于每件物品可以选择放或者不放,具体:
(1)如果j<price[i-1](第i件物品的价格),则不能放入,dp[i][j]=dp[i-1][j];
(2)如果j>=price[i-1],那么可以选择放或者不放,分别对于转移方程:dp[i][j]=dp[i-1][j-price[i-1]]+v[i],dp[i][j]=dp[i-1][j];取两者中较大值,即
dp[i][j]=max{dp[i-1][j-price[i-1]]+v[i],dp[i][j]=dp[i-1][j]}。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int N = scanner.nextInt(); int m= scanner.nextInt(); int[] price=new int[m]; int[] value=new int[m]; int[] ZhuFu=new int[m]; for(int i=0;i<m;i++){ price[i]=scanner.nextInt(); value[i]=scanner.nextInt()*price[i]; //定义 价值=重要度*价格 ZhuFu[i]=scanner.nextInt(); } //采用动态规划 int[][] dp=new int[m+1][N+1]; //dp[i][j]表示用j钱购买i件物品的总价值 for(int i=1;i<=m;i++){ for(int j=1;j<=N;j++){ if(ZhuFu[i-1]==0){ //表示为主件 if(j>=price[i-1]){ dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-price[i-1]]+value[i-1]); //分别表示不买第i件和买第i件物品之后的最大价值 }else{ dp[i][j]=dp[i-1][j]; } }else{ //表示为附件,附件需要购买主件 if(price[i-1]+price[ZhuFu[i-1]-1]<=j){ dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-price[i-1]-price[ZhuFu[i-1]-1]]+value[i-1]); }else{ dp[i][j]=dp[i-1][j]; } } } } System.out.println(dp[m][N]); } } }