1. 程式人生 > >華為線上程式設計題系列-16-購物單

華為線上程式設計題系列-16-購物單

問題描述:

問題描述
問題描述

1. 問題涉及知識點.

  • 動態規劃.

2. 自己解法.

  • 先對資料進行合併.
(原始資料)
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

(因為最後結果是需要和重要性進行加權的,所以提前進行加權)
_______________
800 1600 0 
400 2000 1 
300 1500 1 
400 1200 0 
500 1000 0 

(因為購買主物品時候必須購買附屬品,所以把附屬品加再主物品上)
_______________
(構成動態規劃處理資料)
1500 5100 
400 1200 
500 1000 
_______________
2200
import java.util.Scanner;
public
class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int allMoney = scanner.nextInt(); int N = scanner.nextInt(); int [][]intArr = new int[N][3]; for(int i=0;i<N;i++){ intArr[i][0] = scanner.nextInt(); // 價格
intArr[i][1] = intArr[i][0]*scanner.nextInt(); // 價格 *重要度(評估的價值) intArr[i][2] = scanner.nextInt(); // 附屬屬性 } int result = getResult(allMoney,intArr); System.out.println(result); } private static int getResult(int allMoney, int[][] intArr) { int
N = intArr.length; // System.out.println("_______________"); // Utils.printIntArr2(intArr,N,3); // 把附屬品的價格和價值合併再主件上 int [][]intArr_2 = new int[N+1][2]; int intArr_2Index = 1; for (int[] anIntArr : intArr) { if (anIntArr[2] != 0) { intArr_2[anIntArr[2] - 1][0] = intArr_2[anIntArr[2] - 1][0] + anIntArr[0]; intArr_2[anIntArr[2] - 1][1] = intArr_2[anIntArr[2] - 1][1] + anIntArr[1]; } else { intArr_2[intArr_2Index][0] = anIntArr[0]; intArr_2[intArr_2Index][1] = anIntArr[1]; intArr_2Index++; } } return DP(intArr_2,allMoney,intArr_2Index); } private static int DP(int[][] intArr, int allMoney,int intArr_2Index) { // System.out.println("_______________"); // Utils.printIntArr2(intArr,intArr_2Index,2); // 1 建立陣列 int[][] keyMap = new int[allMoney+1][intArr_2Index];//java會給陣列預設為0.所以不用初始化. // 2 建立keyMap. for(int j=1;j<keyMap.length;j++){ for(int i=1;i<keyMap[j].length;i++){ if(j<intArr[i][0]){ // 不裝 keyMap[j][i] = keyMap[j][i]; }else { //裝 keyMap[j][i] = Math.max(keyMap[j][i-1],intArr[i][1]+keyMap[j-intArr[i][0]][i-1]); } } } // System.out.println("_______________"); // Utils.printIntArr2(keyMap,allMoney+1,intArr_2Index); return keyMap[keyMap.length-1][keyMap[0].length-1]; } }

3. 優質答案.

連結:https://www.nowcoder.com/questionTerminal/f9c6f980eeec43ef85be20755ddbeaf4
來源:牛客網

import java.util.Scanner;

public class Main{

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int sum_money = 0;
        int num = 0;           
        sum_money=sc.nextInt();
        num=sc.nextInt();
        int price[]=new int[num+1];
        int val[]=new int[num+1];
        int[] q = new int[num+1];
        for (int i = 1; i <= num; i++) {
            price[i]=sc.nextInt();
            val[i]=sc.nextInt()*price[i];
            q[i]=sc.nextInt();
        }
        int[][] dp=new int[num+1][sum_money+1];
/*
* 初始值java預設賦值為0,其中dp[0][0...sum_money]為0,從dp[1][0...sum_money]
  計算第1行,代表第一件物品
dp[i][sum_money] : 前i個物體放入容量為sum_money的揹包的最大價值;
dp[i-1][sum_money] : 前i-1個物體放入容量為sum_money的揹包的最大價值;
dp[i-1][sum_money-price[i]] : 前i-1個物體放入容量為sum_money-price[i]的揹包的最大價值;
dp[i][sum_money]=Math.max{dp[i-1][sum_money-price[i]]+val[i] , dp[i-1][sum_money]}
*/
        for (int i = 1; i <=num; i++) {
            for (int j = 1; j <= sum_money; j++) {
                if(q[i]==0)
                {
                    if(price[i]<=j)
                        dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-price[i]]+val[i]);
                }
                if(q[i]>0)
                {
                    if(price[i]+price[q[i]]<=j)
                        dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-price[i]-price[q[i]]]+val[i]+val[q[i]]);
                }
            }

        }
        System.out.println(dp[num][sum_money]);
    }
}

4. 本題總結.

這個題採用動態規劃,動態規劃的思想是把不同時刻的最優質通過陣列的形式記錄下來.再後面計算的時候直接呼叫前面的值,而不用再次計算.
動態規劃的準確率 取決於資料和構造的陣列((容量+1)*(資料量+1))這裡的資料量一定要注意是從0開始還是從1開始,如果是從1開始就不用+1.