Google Code Jam 2020 Qualification Round: Vestigium Solution
Google Code Jam 2020 Qualification Round: Vestigium Solution
Blogger: http://blog.baozitraining.org/2020/05/google-code-jam-2020-qualification.html
Youtube: https://youtu.be/oipVOvqkFVc
博客园: https://www.cnblogs.com/baozitraining/p/12866601.html
B站: https://www.bilibili.com/video/BV16z4y1R7k6/
Problem Statement
Problem
Dr. Patel has N stacks of plates. Each stack contains K plates. Each plate has a positive beauty value, describing how beautiful it looks.
Dr. Patel would like to take exactly P plates to use for dinner tonight. If he would like to take a plate in a stack, he must also take all of the plates above it in that stack as well.
Help Dr. Patel pick the P plates that would maximize the total sum of beauty values.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the three integers N, K and P. Then, N lines follow. The i-th line contains K integers, describing the beauty values of each stack of plates from top to bottom.
Output
For each test case, output one line containing Case #x: y
, where x
is the test case number (starting from 1) and y
is the maximum total sum of beauty values that Dr. Patel could pick.
Limits
Time limit: 20 seconds per test set.
Memory limit: 1GB.
1 ≤ T ≤ 100.
1 ≤ K ≤ 30.
1 ≤ P ≤ N * K.
The beauty values are between 1 and 100, inclusive.
Test set 1
1 ≤ N ≤ 3.
Test set 2
1 ≤ N ≤ 50.
Sample
Input |
Output |
---|---|
22 4 510 10 100 3080 50 10 503 2 380 8015 5020 10 |
Case #1: 250Case #2: 180 |
In Sample Case #1, Dr. Patel needs to pick P = 5 plates:
- He can pick the top 3 plates from the first stack (10 + 10 + 100 = 120).
- He can pick the top 2 plates from the second stack (80 + 50 = 130) .
In total, the sum of beauty values is 250.
In Sample Case #2, Dr. Patel needs to pick P = 3 plates:
- He can pick the top 2 plates from the first stack (80 + 80 = 160).
- He can pick no plates from the second stack.
- He can pick the top plate from the third stack (20).
In total, the sum of beauty values is 180.
Note: Unlike previous editions, in Kick Start 2020, all test sets are visible verdict test sets, meaning you receive instant feedback upon submission.
Problem link
Video Tutorial
You can find the detailed video tutorial here
- Youtube
- B站
Thought Process
First thought is similar to merging multiple lists, this won't work since the lists are not sorted and we are not allowed to sort due to the order constraint.
Second thought is keep a max heap, and always merge the largest value from all the top elements in the lists. This is wrong since greedy won't work here. E.g., below if we want to pick 3 plates, using max heap will pick 2, 2, 2, instead of 1, 1, 100
2, 2, 2, 2, 2
1, 1, 100, 100, 100
Third thought seems we have to brute force, for all the combos of P, we check what's the maximum value. Quote from the analysis, it's exponential time complexity
For example, if N = 3 and for any given values of K and P, generate all possible triples (S1, S2, S3) such that S1+S2+S3 = P and 0 ≤ Si ≤ K. Note: Si is the number of plates picked from the i-th stack. This can be done via recursion and the total time complexity is O(KN) which abides by the time limits.
Forth and final solution to optimize this is using dynamic programming. It's very common in those coding competitions.
Quote from the analysis
First, let's consider an intermediate state dp[i][j] which denotes the maximum sum that can be obtained using the first i stacks when we need to pick j plates in total.
Next, we iterate over the stacks and try to answer the question: What is the maximum sum if we had to pick j plates in total using the i stacks we've seen so far? This would give us dp[i][j]. However, we need to also decide, among those j plates, how many come from the i-th stack? i.e., Let's say we pick x plates from the i-th stack, then dp[i][j] = max(dp[i][j], sum[i][x]+dp[i-1][j-x]). Therefore, in order to pick j plates in total from i stacks, we can pick anywhere between [0, 1, ..., j] plates from the i-th stack and [j, j-1, ..., 0] plates from the previous i-1 stacks respectively. Also, we need to do this for all values of 1 ≤ j ≤ P. The flow would look like: for i [1, N]: for j [0, P]: dp[i][j] := 0 for x [0, min(j, K)]: dp[i][j] = max(dp[i][j], sum[i][x]+dp[i-1][j-x]) If we observe closely, this is similar to the 0-1 Knapsack Problem with some added complexity. To conclude, the overall time complexity would be O(N*P*K).
Solutions
1 public static void main(String[] args) {
2 Scanner s = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
3
4 int testCases = s.nextInt();
5 int caseNum = 1;
6 Plates plates = new Plates();
7
8 while (caseNum <= testCases) {
9 int n = s.nextInt();
10 int k = s.nextInt();
11 int p = s.nextInt();
12
13 int[][] values = new int[n][k];
14 for (int i = 0; i < n; i++) {
15 for (int j = 0; j < k; j++) {
16 values[i][j] = s.nextInt();
17 }
18 }
19
20 System.out.println(String.format("Case #%d: %d", caseNum, plates.maxPlatesBeautyValue(values, p)));
21 caseNum++;
22 }
23 }
24
25 private int maxPlatesBeautyValue(int[][] values, int numberOfPlates) {
26 int n = values.length;
27 int k= values[0].length;
28 int p = numberOfPlates;
29
30
31 // could use a one dimension array
32 int[][] prefixSum = new int[n + 1][k + 1];
33 int[][] lookup = new int[n + 1][p + 1];
34
35 for (int i = 1; i <= n; i++) {
36 for (int j = 1; j <= k; j++) {
37 prefixSum[i][j] = prefixSum[i][j - 1] + values[i - 1][j - 1];
38 }
39 }
40
41 for (int i = 1; i <= n; i++) {
42 for (int j = 1; j <= p; j++) {
43 lookup[i][j] = 0;
44
45 for (int x = 0; x <= Math.min(j, k); x++) {
46 lookup[i][j] = Math.max(lookup[i][j], prefixSum[i][x] + lookup[i - 1][j - x]);
47 }
48 }
49 }
50
51 return lookup[n][p];
52 }
DP solution
Time Complexity: O(N*P*K)
Space Complexity: O(N*max(P, K))
References
- Google kickstart official solution
- 通过shell定制ash脚本(r3笔记第33天)
- 使用shell定制awr脚本(r3笔记第32天)
- 用python对人们使用自行车情况分析与预测
- 由一条sql语句导致的系统IO问题(r3笔记第31天)
- 关于正则表达式第二篇(r3笔记第30天)
- 关于pl/sql的代码保护(r3笔记28天)
- Bilibili (B站)200万用户数据爬取与分析(附源码)
- 关于降低高水位线的尝试(r3笔记47天)
- 简单分析shared pool(二) (r3笔记48天)
- Python股票数据分析
- 简单分析shared pool(一) (r3笔记46天)
- 走索引扫描的慢查询(r3笔记45天)
- AR(I)MA时间序列建模过程——步骤和python代码
- 用python作信用卡欺诈预测
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 关于 Elasticsearch 段合并,这一篇说透了!
- 解了这十道C语言题,你敢说你精通C语言?
- 微服务中使用Maven BOM来管理你的服务版本
- 设计模式之代理模式(文末赠书)
- 使用Spring IoC容器:选BeanFactory还是ApplicationContext?
- Stream使用这么久,它是如何提高遍历集合效率?
- FastDFS 分布式文件系统入门
- 「翻译」 如何Bypass rbash
- 代码审计-.NET下的序列化与反序列化(BinaryFormatter)
- 深入探讨 JavaScript 逻辑赋值运算符
- Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
- 谈谈volatile
- 【V-REP自学笔记(八)】控制youBot抓取和移动物体
- Gson 简单使用姿势小结
- 【SpringBoot WebFlux 系列】WebFlux 之 Path 参数解析与 url 映射