当前位置:网站首页>牛客 HJ16 购物单
牛客 HJ16 购物单
2022-07-31 15:58:00 【顧棟】
描述
王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
| 主件 | 附件 |
|---|---|
| 电脑 | 打印机,扫描仪 |
| 书柜 | 图书 |
| 书桌 | 台灯,文具 |
| 工作椅 | 无 |
如果要买归类为附件的物品,必须先买该附件所属的主件,且每件物品只能购买一次。
每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。
王强查到了每件物品的价格(都是 10 元的整数倍),而他只有 N 元的预算。除此之外,他给每件物品规定了一个重要度,用整数 1 ~ 5 表示。他希望在花费不超过 N 元的前提下,使自己的满意度达到最大。
满意度是指所购买的每件物品的价格与重要度的乘积的总和,假设设第 i i i件物品的价格为 v [ i ] v[i] v[i],重要度为 w [ i ] w[i] w[i],共选中了 k k k件物品,编号依次为 j 1 , j 2 , . . . , j k j_1,j_2,...,j_k j1,j2,...,jk ,则满意度为:编号依次为 v [ j 1 ] ∗ w [ j 1 ] + v [ j 2 ] ∗ w [ j 3 ] + . . . + v [ j k ] ∗ w [ j k ] { v[j_1]*w[j_1]+v[j_2]*w[j_3]+...+v[j_k]*w[j_k] } v[j1]∗w[j1]+v[j2]∗w[j3]+...+v[jk]∗w[jk] (其中 * 为乘号)
请你帮助王强计算可获得的最大的满意度。
输入描述:
输入的第 1 行,为两个正整数N,m,用一个空格隔开:
(其中 N ( N<32000 )表示总钱数, m (m <60 )为可购买的物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)
输出描述:
输出一个正整数,为张强可以获得的最大的满意度。
示例1
输入:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出:
2200
示例2
输入:
50 5
20 3 5
20 3 5
10 3 0
10 2 0
10 1 0
输出:
130
说明:
由第1行可知总钱数N为50以及希望购买的物品个数m为5;
第2和第3行的q为5,说明它们都是编号为5的物品的附件;
第4~6行的q都为0,说明它们都是主件,它们的编号依次为3~5;
所以物品的价格与重要度乘积的总和的最大值为10*1+20*3+20*3=130
java实现
- 使用数组来存放物品,通过下标快速定位物品
- 借助一个实体类GOOD,里面有着物品的价格v重要度p物品类型q 附件1的与附件2的在物品数组中的下标。
package nowcoder.x1x;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class HJ016 {
static class Good {
int v;
int p;
int q;
int sub1;
int sub2;
public Good() {
}
public Good(int v, int p, int q) {
this.v = v;
this.p = p;
this.q = q;
}
public int getV() {
return v;
}
public void setV(int v) {
this.v = v;
}
public int getP() {
return p;
}
public void setP(int p) {
this.p = p;
}
public int getQ() {
return q;
}
public void setQ(int q) {
this.q = q;
}
public int getSub1() {
return sub1;
}
public void setSub1(int sub1) {
this.sub1 = sub1;
}
public int getSub2() {
return sub2;
}
public void setSub2(int sub2) {
this.sub2 = sub2;
}
}
public static int dw = 100;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
boolean flag = true;
// 获取第一行
String line1 = br.readLine();
// 第一行是N,钱的个数 m, 物品的个数
String[] arr = line1.split(" ");
int N = Integer.parseInt(arr[0]);
int m = Integer.parseInt(arr[1]);
Good[] A = new Good[m + 1];
int i = 1;
while (null != (line1 = br.readLine())) {
arr = line1.split(" ");
int v = Integer.parseInt(arr[0]);
int p = Integer.parseInt(arr[1]);
int q = Integer.parseInt(arr[2]);
if (flag) {
if (v % dw != 0) {
flag = false;
dw = 10;
for (int j = 1; j < i; j++) {
A[j].setV(A[j].v * 10);
}
}
}
v = v / dw;
// i可能在下面的q>0时已经进行了初始化
if (null != A[i]) {
A[i].setV(v);
A[i].setP(p);
A[i].setQ(q);
} else {
A[i] = new Good(v, p, q);
}
if (q > 0) {
if (A[q] == null) {
A[q] = new Good();
}
// 优先填充附件一,再去填充附件二
if (A[q].sub1 == 0) {
A[q].setSub1(i);
} else {
A[q].setSub2(i);
}
}
i++;
}
N = N / dw;
dp(N, A);
}
public static void dp(int N, Good[] A) {
int[][] dp = new int[N + 1][A.length];
for (int i = 1; i < A.length; i++) {
// v代表没有附件,v1代表有一个附件sub1.v2代表一个附件2,v3代表2个附件
int v = -1, v1 = -1, v2 = -1, v3 = -1;
int tempdp = -1, tempdp1 = -1, tempdp2 = -1, tempdp3 = -1;
v = A[i].v;
tempdp = v * A[i].p;
// 拥有两个附件
if (A[i].sub1 != 0 && A[i].sub2 != 0) {
v3 = v + A[A[i].sub1].v + A[A[i].sub2].v;
tempdp3 = tempdp + A[A[i].sub1].v * A[A[i].sub1].p + A[A[i].sub2].v * A[A[i].sub2].p;
}
// 只拥有附件1
if (A[i].sub1 != 0) {
v1 = v + A[A[i].sub1].v;
tempdp1 = tempdp + A[A[i].sub1].v * A[A[i].sub1].p;
}
// 只拥有附件2
if (A[i].sub2 != 0) {
v2 = v + A[A[i].sub2].v;
tempdp2 = tempdp + A[A[i].sub2].v * A[A[i].sub2].p;
}
for (int j = 1; j < N + 1; j++) {
// 并非主件
if (A[i].q > 0) {
dp[j][i] = dp[j][i - 1];
} else {
dp[j][i] = dp[j][i - 1];
if (j >= v && v != -1) {
dp[j][i] = Math.max(dp[j][i], dp[j - v][i - 1] + tempdp);
}
if (j >= v1 && v1 != -1) {
dp[j][i] = Math.max(dp[j][i], dp[j - v1][i - 1] + tempdp1);
}
if (j >= v2 && v2 != -1) {
dp[j][i] = Math.max(dp[j][i], dp[j - v2][i - 1] + tempdp2);
}
if (j >= v3 && v3 != -1) {
dp[j][i] = Math.max(dp[j][i], dp[j - v3][i - 1] + tempdp3);
}
}
}
}
System.out.println(dp[N][A.length - 1] * dw);
}
}
边栏推荐
- The arm button controls the flashing of the led light (embedded button experiment report)
- 【7.29】代码源 - 【排列】【石子游戏 II】【Cow and Snacks】【最小生成数】【数列】
- Oracle dynamically registers non-1521 ports
- [7.28] Code Source - [Fence Painting] [Appropriate Pairs (Data Enhanced Version)]
- Implementing distributed locks based on Redis (SETNX), case: Solving oversold orders under high concurrency
- 软件实现AT命令操作过程
- 6. 使用 Postman 工具高效管理和测试 SAP ABAP OData 服务
- C程序是如何跑起来的01 —— 普通可执行文件的构成
- SHELL内外置命令
- [MySQL] Mysql paradigm and the role of foreign keys
猜你喜欢

The 2nd China PWA Developer Day

BGP综合实验(建立对等体、路由反射器、联邦、路由宣告及聚合)

leetcode303 Weekly Match Replay

基于ABP实现DDD
![[MySQL] Mysql paradigm and the role of foreign keys](/img/9d/a4295de26683d7bca2b8e9d14f754b.png)
[MySQL] Mysql paradigm and the role of foreign keys

外媒所言非虚,苹果降价或许是真的在清库存

LevelSequence源码分析

C language "the third is" upgrade (mode selection + AI chess)

Grafana安装后web打开报错

Getting Started with TextBlock Control Basic Tools Usage, Get Started
随机推荐
复制延迟案例(3)-单调读
How to switch remote server in gerrit
Implementing DDD based on ABP
Website vulnerability repair service provider's analysis of unauthorized vulnerability
利用PHP开发具有注册、登陆、文件上传、发布动态功能的网站
Applicable Scenarios of Multi-Master Replication (1) - Multi-IDC
7. Summary of common interview questions
MySQL数据库操作
.NET 20周年专访 - 张善友:.NET 技术是如何赋能并改变世界的
The arm button controls the flashing of the led light (embedded button experiment report)
Foreign media right, apple on May be true in inventory
EF Core 2.2中将ORM框架生成的SQL语句输出到控制台
Deployment应用生命周期与Pod健康检查
软件实现AT命令操作过程
【7.29】Code Source - 【Arrangement】【Stone Game II】【Cow and Snacks】【Minimum Number of Spawns】【Sequence】
Browser's built-in color picker
小程序:matlab解微分方程「建议收藏」
MySQL database operations
Doing things software development - the importance of law and understanding of reasonable conclusions
第二届中国PWA开发者日