问题描述:
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.