# Google Kickstart 2020
- [Google Kickstart 2020](#google-kickstart-2020)
- [Round A](#round-a)
- [A. Allocation](#a-allocation)
- [题目大意](#题目大意)
- [解析](#解析)
- [代码](#代码)
- [B. Plates](#b-plates)
- [题目大意](#题目大意-1)
- [解析](#解析-1)
- [代码](#代码-1)
- [C. Workout](#c-workout)
- [题目大意](#题目大意-2)
- [解析 1](#解析-1)
- [代码 1](#代码-1)
- [解析 2](#解析-2)
- [代码 2](#代码-2)
- [D. Bundling](#d-bundling)
- [题目大意](#题目大意-3)
- [解析](#解析-2)
- [代码](#代码-2)
- [Round B](#round-b)
- [A. Bike Tour](#a-bike-tour)
- [题目大意](#题目大意-4)
- [解析](#解析-3)
- [代码](#代码-3)
- [B. Bus Routes](#b-bus-routes)
- [题目大意](#题目大意-5)
- [解析](#解析-4)
- [代码](#代码-4)
- [C. Robot Path Decoding](#c-robot-path-decoding)
- [题目大意](#题目大意-6)
- [解析](#解析-5)
- [代码](#代码-5)
- [D. Wandering Robot](#d-wandering-robot)
- [题目大意](#题目大意-7)
- [解析](#解析-6)
- [代码](#代码-6)
## Round A
### A. Allocation
#### 题目大意
总共 N 个房子,价格不同,求 B 美元最多可以买多少房子。
#### 解析
将所有房子价格排序,然后求前缀和,前缀和大于 B 的地方前面所有房子就是 B 这么多钱能够购买的最多的房子总数。
#### 代码
```cpp
#include <algorithm>
#include <iostream>
using namespace std;
int t, n, a[100005], b;
int solve() {
sort(a, a + n);
int i = 0;
for (; i < n; i++) {
if (i != 0) {
a[i] = a[i - 1] + a[i];
}
if (a[i] > b) break;
}
return i;
}
int main() {
cin >> t;
for (int i = 1; i <= t; i++) {
cin >> n >> b;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
printf("Case #%d: %d\n", i, solve());
}
return 0;
}
```
### B. Plates
#### 题目大意
现有 N 叠盘子,每叠有 K 个盘子,每个盘子一个价值,要从这 N 叠盘子中取 P 个盘子,最大化价值总和。限制是要取出一个盘子,这个盘子之上的所有盘子都要取出来。
#### 解析
因为要取一个盘子,就需要取出这个盘子之上的所有盘子,我们同样先求出前缀和,用来表示取出一个盘子及其上面所有盘子取得的总价值。
使用深度优先搜索,第 i 叠盘子选择 $k_i$ 个盘子,对后续所有情况得到的价值取最大值。可以加入缓存对 dfs 运行结果进行存储。
#### 代码
```cpp
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;
int t, n, k, p, v[55][35];
// 缓存 dfs 结果
map<int, map<int, int>> m;
int dfs(int stack_no, int p) {
if (m.count(stack_no) && m[stack_no].count(p)) {
return m[stack_no][p];
}
if (p == 0) return 0;
if (stack_no == n - 1) return v[stack_no][min(p - 1, k - 1)];
int res = 0;
// i 表示第 stack_no 叠盘子选择的盘子总数
for (int i = 0; i <= min(p, k); i++) {
// value 表示此次选择带来的收益价值
int value = 0;
if (i != 0) {
value = v[stack_no][i - 1];
}
res = max(res, dfs(stack_no + 1, p - i) + value);
}
m[stack_no][p] = res;
return res;
}
int solve() {
// Prefix sum calculation
for (int a = 0; a < n; a++) {
for (int b = 0; b < k; b++) {
if (b != 0) {
v[a][b] = v[a][b - 1] + v[a][b];
}
}
}
// DFS
return dfs(0, p);
}
int main() {
cin >> t;
for (int i = 1; i <= t; i++) {
m.clear();
cin >> n >> k >> p;
for (int a = 0; a < n; a++) {
for (int b = 0; b < k; b++) {
cin >> v[a][b];
}
}
printf("Case #%d: %d\n", i, solve());
}
return 0;
}
```
### C. Workout
#### 题目大意
N 次锻炼,第 i 次锻炼时间为 $M_i$,时间单调递增,定义最大的相邻时间差为锻炼难度,在 N 次锻炼中插入 K 次新的锻炼(保持单调递增),使得难度尽量小,求最小的难度值。
#### 解析 1
> 这种方法时间复杂度比较高,最终在 Test set 2 TLE 了。
以 9 10 20 26 30 为例,时间差分别为 1, 10, 6, 4,排序之后为 10, 6, 4, 1,将其组织成一个最大堆,每次取出堆顶的元素将其一分为二。一共六次机会,依次操作如下:
1. 6, 5, 5, 4, 1
2. 5, 5, 4, 3, 3, 1
3. 5, 4, 3, 3, 3, 2, 1
4. 4, 3, 3, 3, 3, 2, 2, 1
5. 3, 3, 3, 3, 2, 2, 2, 2, 1
6. 3, 3, 3, 2, 2, 2, 2, 2, 1, 1
最终返回堆顶元素值 3。
对于 1, 7, 9 可以插入 2 个值的情况,按照上述步骤,应该依次是:
1. 1, 4, 7, 9
2. 1, 2, 4, 7, 9
最终返回的最大差值是 3。
但是实际情况是,可以插入为 1, 3, 5, 7, 9,最终的最大差值为 2,上面的方案并不是最优解。这里的关键是可以不是二分,而是三等分。
从上面的分析中可以看出,将 $M_i$ 和 $M_{i+1}$ 中插入 k 次锻炼,这两次锻炼之间的最小的难度变为 $\lceil \frac{M_i - M_{i+1}}{k + 1} \rceil$。
经过上面的分析,算法思路如下:
1. 预先算出差值数组
2. 使用深度优先搜索,第 i 个差值插入 $k_i$ 次锻炼,对后续所有情况取最小值即可。计算过程中需要使用map进行缓存。
#### 代码 1
> 这种方法时间复杂度比较高,最终在 Test set 2 TLE 了。
```cpp
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;
int t, n, k, m[100005];
// 缓存 dfs 结果
map<int, map<int, int>> mp;
int diff(int d, int k) {
return int(ceil(d / (k + 1.0)));
}
int dfs(int workout_idx, int k) {
if (mp.count(workout_idx) && mp[workout_idx].count(k)) {
return mp[workout_idx][k];
}
// 总共 n - 1 个间隔
if (workout_idx == n - 1 - 1) {
return mp[workout_idx][k] = diff(m[workout_idx], k);
}
int res = INT32_MAX;
// i 表示用 i 个新的锻炼来划分原有的锻炼
for (int i = 0; i <= k; i++) {
int tmp = diff(m[workout_idx], i);
int sub_value = dfs(workout_idx + 1, k - i);
// 后面的所有插入情况中,取最优情况
res = min(res, max(tmp, sub_value));
// 剪枝:再给此处增加锻炼数没用了,只会造成偏斜越来越严重
if (tmp <= sub_value) break;
}
mp[workout_idx][k] = res;
return res;
}
int solve() {
return dfs(0, k);
}
int main() {
cin >> t;
for (int i = 1; i <= t; i++) {
mp.clear();
cin >> n >> k;
int prev, cur;
for (int i = 0; i < n; i++) {
cin >> cur;
if (i != 0) {
m[i - 1] = cur - prev;
}
prev = cur;
}
printf("Case #%d: %d\n", i, solve());
}
return 0;
}
```
#### 解析 2
直接遍历所有可能的解,去判断要生成这个解需要插入的锻炼个数 $K'$ 是否小于 K,如果小于,就可以满足。对解的搜索可以采用二分查找。
锻炼时长 $M_i$, $M_{i+1}$ 需要变为难度 $d$ 至少需要插入 $\lceil \frac{M_{i+1} - M_i}{d} - 1 \rceil$ 个新的锻炼。
#### 代码 2
```cpp
#include <iostream>
using namespace std;
int t, n, k, m[100005], max_diff;
// 单个间隔降到难度 d 至少需要的插入个数
int single_insert_num(int delta_m, int d) {
int cnt = 0, tmp = 0;
while (tmp < delta_m) {
cnt++;
tmp += d;
}
return cnt - 1;
}
// 总体降到难度 d 至少需
没有合适的资源?快使用搜索试试~ 我知道了~
acwing, leetcode, kickstart, 算法模板, PAT 等等.zip
共1808个文件
cpp:1053个
js:393个
ts:169个
需积分: 5 1 下载量 64 浏览量
2024-02-04
10:59:18
上传
评论
收藏 1.38MB ZIP 举报
温馨提示
acwing, leetcode, kickstart, 算法模板, PAT 等等
资源推荐
资源详情
资源评论
收起资源包目录
acwing, leetcode, kickstart, 算法模板, PAT 等等.zip (1808个子文件)
169. 数独2.cpp 8KB
276. I-区域.cpp 7KB
174. 推箱子.cpp 6KB
253. 普通平衡树.cpp 6KB
181. 回转游戏.cpp 5KB
segmentTreeLazy.cpp 5KB
1026.cpp 5KB
D. Binary Operator.cpp 5KB
L2-028 秀恩爱分得快.cpp 5KB
258. 石头剪子布.cpp 5KB
179. 八数码.cpp 5KB
1086. 恨7不成妻.cpp 5KB
2020D-D.cpp 5KB
5619.cpp 5KB
185. 玛雅游戏.cpp 4KB
182. 破坏正方形.cpp 4KB
2020G-C.cpp 4KB
D. Candies.cpp 4KB
245. 你能回答这些问题吗.cpp 4KB
D-Golden_Stone.cpp 4KB
2034. Stock Price Fluctuation.cpp 4KB
192. 立体推箱子2.cpp 4KB
C-Toys.cpp 4KB
261. 旅馆.cpp 4KB
1026. Table Tennis (30) .cpp 4KB
281. 硬币.cpp 4KB
2020G-D.cpp 4KB
246. 区间最大公约数.cpp 4KB
1095.cpp 4KB
5783. 设计电影租借系统.cpp 4KB
259. 真正的骗子.cpp 4KB
177. 噩梦.cpp 4KB
105. 七夕祭.cpp 4KB
treeTraversal.cpp 4KB
D. Truck Delivery.cpp 4KB
c-Star Trappers.cpp 4KB
2020D-D-naive.cpp 3KB
172. 立体推箱子.cpp 3KB
5688. 由子序列构造的最长回文串的长度.cpp 3KB
L3-007. 天梯地图 .cpp 3KB
151. 表达式计算4.cpp 3KB
153. 双栈排序.cpp 3KB
265. 营业额统计.cpp 3KB
166. 数独.cpp 3KB
1613. 数独简单版.cpp 3KB
248. 窗内的星星.cpp 3KB
190. 字串变换.cpp 3KB
2019A-B.cpp 3KB
1139.cpp 3KB
155. 内存分配.cpp 3KB
119. 袭击.cpp 3KB
136. 邻值查找.cpp 3KB
2019A-B-oldwrong.cpp 3KB
1111. Online Map (30) .cpp 3KB
191. 天气预报.cpp 3KB
C. Catch Some.cpp 3KB
277. 饼干.cpp 3KB
180. 排书.cpp 3KB
247. 亚特兰蒂斯.cpp 3KB
5770. 反转表达式值的最少操作次数.cpp 3KB
5826. Delete Duplicate Folders in System.cpp 3KB
178. 第K短路.cpp 3KB
128. 编辑器.cpp 3KB
1111.cpp 3KB
AcWing 3516. 最大面积.cpp 3KB
D.cpp 3KB
130. 火车进出栈问题.cpp 3KB
103. 电影.cpp 3KB
243. 一个简单的整数问题2.cpp 3KB
131. 直方图中最大的矩形.cpp 3KB
240. 食物链.cpp 3KB
176. 装满的油箱.cpp 3KB
114. 国王游戏.cpp 3KB
1159. Structure of a Binary Tree (30).cpp 3KB
794. 高精度除法-高精度除以高精度.cpp 3KB
2019A-C.cpp 3KB
binarySearch.cpp 3KB
2019G-B.cpp 3KB
1081. 度的数量.cpp 3KB
186. 巴士.cpp 3KB
2020F-C.cpp 3KB
5811. Painting a Grid With Three Different Colors.cpp 3KB
120. 防线.cpp 3KB
243. 一个简单的整数问题2.cpp 3KB
B-High_Buildings.cpp 3KB
1228. 油漆面积-O(N^2).cpp 3KB
1923. Longest Common Subpath.cpp 3KB
A. Wiggle Walk.cpp 2KB
1632.cpp 2KB
947.most-stones-removed-with-same-row-or-column.cpp 2KB
167. 木棒.cpp 2KB
239. 奇偶游戏.cpp 2KB
1123. Is It a Complete AVL Tree (30).cpp 2KB
5810. Merge BSTs to Create Single BST.cpp 2KB
168. 生日蛋糕.cpp 2KB
binaryLifting.cpp 2KB
109. 天才ACM.cpp 2KB
5787. The Earliest and Latest Rounds Where Players Compete.cpp 2KB
147. 数据备份.cpp 2KB
1728. Cat and Mouse II.cpp 2KB
共 1808 条
- 1
- 2
- 3
- 4
- 5
- 6
- 19
资源评论
码农阿豪
- 粉丝: 1w+
- 资源: 1754
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功