1. 程式人生 > >華為機試:購物單(考點:動態規劃)

華為機試:購物單(考點:動態規劃)

題目:


分析:這是一道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]);
        }
    }
}