🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员
✨ 本系列打算持续跟新滴滴近期的春秋招笔试题汇总~
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
文章目录
01.K小姐的装修优惠
问题描述
K小姐正在装修她新买的房子。装修商场为她提供了 n n n 种不同的装修材料选择,价格分别为 P 1 , P 2 , . . . , P n P_1, P_2, ..., P_n P1,P2,...,Pn 元。为了吸引顾客,商场推出了 m m m 种优惠方案。每一种优惠方案都对应一个数字 a i a_i ai,表示如果K小姐一次性购买恰好 a i a_i ai 种材料,就可以在这些材料中价格最低的那一种上获得全额优惠。
K小姐打算一次性购买所需的全部材料,并只使用一次优惠方案,她希望在获得优惠后的总花费最少。请你帮助她计算出这个最小总花费。
输入格式
第一行包含两个正整数 n n n 和 m m m,分别表示装修材料的种类数量和优惠方案的数量。
第二行包含 n n n 个正整数 P 1 , P 2 , . . . , P n P_1, P_2, ..., P_n P1,P2,...,Pn,用空格分隔,表示每种装修材料的价格。
第三行包含 m m m 个正整数 a 1 , a 2 , . . . , a m a_1, a_2, ..., a_m a1,a2,...,am,用空格分隔,表示每种优惠方案对应的材料种类数量。
输出格式
输出一行,包含一个整数,表示K小姐使用优惠后的最小总花费。
样例输入
3 2
90 30 40
2 3
样例输出
120
数据范围
- 对于所有评测用例, 1 < n , m < 50000 1 < n, m < 50000 1<n,m<50000
- 1 ≤ a i ≤ n 1 \le a_i \le n 1≤ai≤n
- 1 ≤ P i ≤ 1 0 4 1 \le P_i \le 10^4 1≤Pi≤104
题解
我们可以按照以下步骤解决这个问题:
- 先对所有材料价格进行排序,得到一个从小到大排列的价格序列。
- 对于每一种优惠方案,找到价格序列中最后 a i a_i ai 个价格中的最小值 m i n i min_i mini,它就是使用该优惠方案可以节省的最大金额。
- 在所有的 m i n i min_i mini 中找到最大值 m a x _ m i n max\_min max_min,对应的优惠方案就是最优方案。
- 总花费为所有材料价格之和减去 m a x _ m i n max\_min max_min。
实现上,我们先对价格排序,然后遍历所有优惠方案,维护一个全局最大的 m a x _ m i n max\_min max_min 变量即可。算法的时间复杂度为 O ( n log n + m ) O(n \log n + m) O(nlogn+m),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> prices(n);
for (int i = 0; i < n; i++) {
cin >> prices[i];
}
vector<int> nums(m);
for (int i = 0; i < m; i++) {
cin >> nums[i];
}
sort(prices.begin(), prices.end());
int max_min = 0;
for (int num : nums) {
int min_price = *min_element(prices.end() - num, prices.end());
max_min = max(max_min, min_price);
}
int total_cost = accumulate(prices.begin(), prices.end(), 0);
cout << total_cost - max_min << endl;
return 0;
}
02.LYA小姐的物流规划
问题描述
LYA小姐是一家物流公司的运营经理,负责管理城市内的物流配送。该城市可以看作是一个由 n n n 行 m m m 列的网格构成,部分网格是建筑物或障碍物,因此不可通行。公司的仓库位于 ( X A , Y A ) (X_A, Y_A) (XA,YA),需要将货物先运送到集散中心 ( X B , Y B ) (X_B, Y_B) (XB,YB),然后再配送至客户 ( X C , Y C ) (X_C, Y_C) (XC,YC) 的指定地点。运输车辆只能在相邻的可通行网格之间移动。请你帮助LYA小姐计算出,完成这次配送需要的最少移动步数。
输入格式
第一行包含两个正整数 n n n 和 m m m,表示网格城市的行数和列数。
接下来
n
n
n 行,每行包含
m
m
m 个字符,用于描述网格的可通行状态。其中 #
表示不可通行的网格,.
表示可通行的网格。
最后一行包含六个正整数 X A , Y A , X B , Y B , X C , Y C X_A, Y_A, X_B, Y_B, X_C, Y_C XA,YA,XB,YB,XC,YC,分别表示仓库、集散中心和客户地点的网格坐标。
输出格式
输出一个整数,表示完成配送的最少移动步数。
样例输入
7 8
........
.#.#####
.#...#..
.#.#.#.#
.#.#....
##.###.#
.....#..
5 1 1 7 2 3
样例输出
15
数据范围
- 1 ≤ n , m ≤ 1000 1 \le n, m \le 1000 1≤n,m≤1000
- 1 ≤ X A , X B , X C ≤ n 1 \le X_A, X_B, X_C \le n 1≤XA,XB,XC≤n
- 1 ≤ Y A , Y B , Y C ≤ m 1 \le Y_A, Y_B, Y_C \le m 1≤YA,YB,YC≤m
- 给定的起点、集散中心和客户地点坐标位于可通行网格上,且至少存在一条路径连接它们。
题解
我们可以使用广度优先搜索 (BFS) 的方法来解决这个问题。具体做法如下:
- 从集散中心 ( X B , Y B ) (X_B, Y_B) (XB,YB) 开始,进行 BFS 遍历,计算出每个可通行网格与集散中心的最短距离,记录在二维数组 d i s t dist dist 中。
- 然后计算仓库 ( X A , Y A ) (X_A, Y_A) (XA,YA) 与集散中心的最短距离 d 1 = d i s t [ X A − 1 ] [ Y A − 1 ] d_1 = dist[X_A-1][Y_A-1] d1=dist[XA−1][YA−1],客户地点 ( X C , Y C ) (X_C, Y_C) (XC,YC) 与集散中心的最短距离 d 2 = d i s t [ X C − 1 ] [ Y C − 1 ] d_2 = dist[X_C-1][Y_C-1] d2=dist[XC−1][YC−1]。
- 最终的最短路径长度就是 d 1 + d 2 d_1 + d_2 d1+d2。
在实现上,我们可以使用队列来进行 BFS 遍历。时间复杂度为 O ( n m ) O(nm) O(nm),空间复杂度为 O ( n m ) O(nm) O(nm)。
参考代码
- Cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int bfs(vector<vector<char>>& grid, int x, int y) {
int n = grid.size(), m = grid[0].size();
vector<vector<int>> dist(n, vector<int>(m, -1));
dist[x][y] = 0;
queue<pair<int, int>> q;
q.push({x, y});
vector<int> dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
while (!q.empty()) {
auto [x, y] = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == '.' && dist[nx][ny] == -1) {
dist[nx][ny] = dist[x][y] + 1;
q.push({nx, ny});
}
}
}
return dist;
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<char>> grid(n, vector<char>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> grid[i][j];
}
}
int xa, ya, xb, yb, xc, yc;
cin >> xa >> ya >> xb >> yb >> xc >> yc;
xa--, ya--, xb--, yb--, xc--, yc--;
auto dist = bfs(grid, xb, yb);
int d1 = dist[xa][ya], d2 = dist[xc][yc];
cout << d1 + d2 << endl;
return 0;
}
写在最后
📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取~