華為機試:購物單(考點:動態規劃)
阿新 • • 發佈:2019-01-31
題目:
分析:這是一道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]); } } }