概述
1、题目描述
2、思路分析
1、本题属于依赖背包问题:
有四种情况:
只取主件:f[i-1,j-a[i,0]]+a[i,0]*b[i,0]
取主件+附件1:f[i-1,j-a[i,0]-a[i,1]]+a[i,0]*b[i,0]+a[i,1]*b[i,1]
取主件+附件2:f[i-1,j-a[i,0]-a[i,2]]+a[i,0]*b[i,0]+a[i,2]*b[i,2]
既主件+附件1+附件2:f[i-1,j-a[i,0]-a[i,1]-a[i,2]]+a[i,0]*b[i,0]+a[i,1]*b[i,1]+a[i,2]*b[i,2]
含义:
f[i,j]表示用j元钱,买第i类物品,所得的最大价值
a[i,0]表示第i类物品主件的价格
a[i,1]表示第i类物品第1个附件的价格
a[i,2]表示第i类物品第2个附件的价格
b[i,0],b[i,1],b[i,2]分别表示主件、第1个附件和第2个附件的重要度。
需要在满足金额money内,买到最大价值的物品。价值=价格*重要度
2、使用二维数组加状态方程:
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();
//二维数组,第i行表示第i个物品的价值,列:0表示主键,1表示附件1,2表示附件2
int[][] V = new int[M + 1][3];
//二维数组,第i行表示第i个物品的重要程度,列:0表示主键,1表示附件1,2表示附件2
int[][] P = new int[M + 1][3];
for (int i = 1; i <= M; i++) {
int v = scanner.nextInt();
int p = scanner.nextInt();
int q = scanner.nextInt();
if (q == 0) { //q=0代表是主件
V[i][0] = v;
P[i][0] = p;
} else { //q>0代表是附件,q代表附件所属的主件编号
if (V[q][1] == 0) {
V[q][1] = v;
P[q][1] = p;
} else {
V[q][2] = v;
P[q][2] = p;
}
}
}
//下面正式开始动态规划算法
int[][] dp = new int[M + 1][N + 1];
/**
* 1、钱够用的时候,买不买主键
* 2、钱够用的时候,买不买主键、附件1
* 3、钱够用的时候,买不买主键、附件2
* 4、钱够用的时候,买不买主键、附件1、附件2
* 5、钱不够用的时候,只买前i-1件商品
*/
for (int i = 1; i <= M; i++) {
for (int j = 10; j <= N; j +=10) {
if (j >= V[i][0]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - V[i][0]] + V[i][0] * P[i][0]);
} else if (j >= V[i][0] + V[i][1]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - V[i][0] - V[i][1]] + V[i][0] * P[i][0] + V[i][1] * P[i][1]);
} else if (j >= V[i][0] + V[i][2]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - V[i][0] - V[i][2]] + V[i][0] * P[i][0] + V[i][2] * P[i][2]);
} else if (j >= V[i][0] + V[i][1] + V[i][2]) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - V[i][0] - V[i][1] - V[i][2]] + V[i][0] * P[i][0] + V[i][1] * P[i][1] + V[i][2] * P[i][2]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
System.out.println(dp[M][N]);
}
}
}
不知道为什么通过率只有20%,总感觉牛客的测试数据有问题。
3、将二维数组优化为一维数组加状态方程:
import java.util.Scanner;
public class Main3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) {
//总钱数
int N = sc.nextInt();
//总物品数
int M = sc.nextInt();
//二维数组,第i行表示第i个物品的价值,列:0表示主键,1表示附件1,2表示附件2
int[][] V = new int[M+1][3];
//二维数组,第i行表示第i个物品的重要程度,列:0表示主键,1表示附件1,2表示附件2
int[][] P = new int[M+1][3];
for (int i = 1; i <= M; i++) {
int v = sc.nextInt();
int p = sc.nextInt();
int q = sc.nextInt();
if (q == 0) {
V[i][0] = v;
P[i][0] = p;
} else {
if (V[q][1]==0) {
V[q][1] = v;
P[q][1] = p;
}
else {
V[q][2] = v;
P[q][2] = p;
}
}
}
//记录最大价值
int[] dp = new int[N+1];
/**
* 1、钱够用的时候,买不买主键
* 2、钱够用的时候,买不买主键、附件1
* 3、钱够用的时候,买不买主键、附件2
* 4、钱够用的时候,买不买主键、附件1、附件2
* 5、钱不够用的时候,只买前i-1件商品
*/
for (int i = 1; i <= M; i++)
for (int j = N; j >= 10; j-=10) {
if (j >= V[i][0])
dp[j] = Math.max(dp[j], dp[j-V[i][0]]+V[i][0]*P[i][0]);
if (j >= V[i][0]+V[i][1])
dp[j] = Math.max(dp[j], dp[j-V[i][0]-V[i][1]]+V[i][0]*P[i][0]+V[i][1]*P[i][1]);
if (j >= V[i][0]+V[i][2])
dp[j] = Math.max(dp[j], dp[j-V[i][0]-V[i][2]]+V[i][0]*P[i][0]+V[i][2]*P[i][2]);
if (j >= V[i][0]+V[i][1]+V[i][2])
dp[j] = Math.max(dp[j], dp[j-V[i][0]-V[i][1]-V[i][2]]+V[i][0]*P[i][0]+V[i][1]*P[i][1]+V[i][2]*P[i][2]);
}
System.out.println(dp[N]);
}
}
}
优化为一维数组后,通过率为100%,所以还是不清楚问题在哪儿,思路相同,一个对了,一个不对。
最后
以上就是霸气板栗为你收集整理的华为机试练习_16:购物单(有依赖的背包问题)的全部内容,希望文章能够帮你解决华为机试练习_16:购物单(有依赖的背包问题)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复