華為線上程式設計題系列-16-購物單
阿新 • • 發佈:2019-01-05
問題描述:
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.