题库5文档beta_3
1 跳格子得分最大化
题目
小明和朋友们一起玩跳格子游戏, 每个格子上有特定的分数 score = [1, -1, -6, 7, -17, 7], 从起点score[0]开始,每次最大的步长为k,请你返回小明跳到终点 score[n-1] 时,能得到的最大得分。
输入描述
第一行输入总的格子数量 n 第二行输入每个格子的分数 score[i] 第三行输入最大跳的步长 k
输出描述
输出最大得分
备注 格子的总长度 n 和步长 k 的区间在 [1, 100000] 每个格子的分数 score[i] 在 [-10000, 10000] 区间中
用例
输入
6
1 -1 -6 7 -17 7
2
输出
14
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <climits>
using namespace std;
int getMaxScore(int n, vector<int>& score, int k) {
vector<int> dp(n, INT_MIN);
dp[0] = score[0];
deque<int> deque;
deque.push_back(0);
for (int i = 1; i < n; ++i) {
// 移除超出步长范围的元素
while (!deque.empty() && deque.front() < i - k) {
deque.pop_front();
}
// 当前格子的最大得分
dp[i] = dp[deque.front()] + score[i];
// 维护双端队列,保持dp[deque]中从大到小的顺序
while (!deque.empty() && dp[i] >= dp[deque.back()]) {
deque.pop_back();
}
deque.push_back(i);
}
return dp[n-1];
}
int main() {
int n;
cin >> n;
vector<int> score(n);
for (int i = 0; i < n; ++i) {
cin >> score[i];
}
int k;
cin >> k;
cout << getMaxScore(n, score, k) << endl;
return 0;
}
2 CSV 单元格引用替换
题目
将一个 csv 格式的数据文件中包含有单元格引用的内容替换为对应单元格内容的实际值。 comma separated values(CSV) 逗号分隔值,csv 格式的数据文件使用逗号 "," 作为分隔符将各单元的内容进行分隔。
输入描述
1、输入只有一行数据,用逗号分隔每个单元格,行尾没有逗号。最多26个单元格,对应编号A~Z。 2、每个单元格的内容包含字母和数字,以及使用 '<>' 分隔的单元格引用,例如:<A>表示引用第一个单元的值。 3、每个单元格的内容,在替换前和替换后均不超过100个字符。 4、引用单元格的位置不受限制,允许排在后面的单元格被排在前面的单元格引用。 5、不存在循环引用的情况,比如下面这种场景是不存在的:
A单元恪:aCd<B>8U
B单元格:KAy<A>uZq0
6、不存在多重 '<>' 的情况,一个单元只能引用一个其他单元格。比如下面这种场景是不存在的:
A单元格:aCdOu
B单元格:kAydzco
C单元格:y<<A><B>>d
输出描述
输出替换后的结果
用例
输入
1,2<A>00
输出
1,2100
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <stdexcept>
using namespace std;
vector<string> split(const string &str, char delim) {
vector<string> tokens;
stringstream ss(str);
string token;
while (getline(ss, token, delim)) {
tokens.push_back(token);
}
return tokens;
}
string resolveReference(vector<string> &cells, const string &cell) {
string resolvedCell = cell;
size_t start = resolvedCell.find('<');
size_t end = resolvedCell.find('>');
if (start != string::npos && end != string::npos) {
string reference = resolvedCell.substr(start + 1, end - start - 1);
if (reference.length() != 1 || reference[0] < 'A' || reference[0] > 'Z') {
throw invalid_argument("Invalid reference");
}
int refIndex = reference[0] - 'A';
if (refIndex >= cells.size()) {
throw invalid_argument("Invalid reference");
}
resolvedCell = resolvedCell.substr(0, start) + cells[refIndex] + resolvedCell.substr(end + 1);
}
return resolvedCell;
}
void validateCells(const vector<string> &cells) {
for (const auto &cell : cells) {
if (cell.find('$') != string::npos || cell.length() > 100) {
throw invalid_argument("Invalid cell content");
}
}
}
int main() {
string input;
getline(cin, input);
vector<string> cells = split(input, ',');
if (cells.size() > 26) {
cout << -1 << endl;
return 0;
}
try {
validateCells(cells);
bool hasReference;
do {
hasReference = false;
for (int i = 0; i < cells.size(); i++) {
string resolvedCell = resolveReference(cells, cells[i]);
if (resolvedCell != cells[i]) {
hasReference = true;
cells[i] = resolvedCell;
}
}
} while (hasReference);
for (int i = 0; i < cells.size(); i++) {
if (i != 0) cout << ",";
cout << cells[i];
}
cout << endl;
} catch (const invalid_argument &e) {
cout << -1 << endl;
}
return 0;
}
3 最大运输利润计算
题目
老李是货运公司承运人,老李的货车额定载货重量为 wt。 现有两种货物: 货物 A 单件重量为 wa,单件运费利润为 pa 货物 B 单件重量为 wb,单件运费利润为 pb 老李每次发车时载货总重量刚好为货车额定的载货重量 wt,车上必须同时有货物 A 和货物 B ,货物A、B不可切割。 老李单次满载运输可获得的最高利润是多少?
输入描述
第一列输入为货物 A 的单件重量 wa,0 < wa < 10000 第二列输入为货物 B 的单件重量 wb,0 < wb < 10000 第三列输入为货车的额定载重 wt,0 < wt < 100000 第四列输入为货物 A 的单件运费利润 pa,0 < pa < 1000 第五列输入为货物 B 的单件运费利润 pb,0 < pb < 1000
输出描述
单次满载运输的最高利润
用例
输入
10 8 36 15 7
输出
44
#include <iostream>
#include <algorithm>
using namespace std;
int maxProfit(int wa, int wb, int wt, int pa, int pb) {
int maxProfit = 0;
for (int i = 1; i * wa < wt; i++) {
int remainingWeight = wt - i * wa;
if (remainingWeight % wb == 0) {
int j = remainingWeight / wb;
maxProfit = max(maxProfit, i * pa + j * pb);
}
}
return maxProfit;
}
int main() {
int wa, wb, wt, pa, pb;
cin >> wa >> wb >> wt >> pa >> pb;
cout << maxProfit(wa, wb, wt, pa, pb) << endl;
return 0;
}
4 找到二进制中1的个数相同的最小较大数
题目
小扇和小船今天又玩起来了数字游戏,小船给小扇一个正整数 n(1 ≤ n ≤ 1e9),小扇需要找到一个比 n 大的数字 m,使得 m 和 n 对应的二进制中 1 的个数要相同,如: 4对应二进制100 8对应二进制1000 其中1的个数都为1个 现在求 m 的最小值。
输入描述
输入一个正整数 n(1 ≤ n ≤ 1e9)
输出描述
输出一个正整数 m
用例
输入
2
输出
4
#include <iostream>
using namespace std;
int findNextNumberWithSameBitCount(int n) {
int c = n;
int c0 = 0;
int c1 = 0;
// 计算 c0 和 c1
while ((c & 1) == 0 && (c != 0)) {
c0++;
c >>= 1;
}
while ((c & 1) == 1) {
c1++;
c >>= 1;
}
// 如果 n 是形如 111...000... 这种情况,直接返回 -1
if (c0 + c1 == 31 || c0 + c1 == 0) {
return -1;
}
// 找到右边第一个非拖尾的0位
int p = c0 + c1;
// 将第 p 位设为1
n |= (1 << p);
// 将 p 右边的所有位清零
n &= ~((1 << p) - 1);
// 在右边插入 (c1-1) 个 1
n |= (1 << (c1 - 1)) - 1;
return n;
}
int main() {
int n;
cin >> n;
cout << findNextNumberWithSameBitCount(n) << endl;
return 0;
}
5 精确最长匹配分词(答案微差)
题目
给定一个连续不包含空格的字符串,该字符串仅包含英文小写字母及英文标点符号(逗号、分号、句号),同时给定词库,对该字符串进行精确分词。
说明:
精确分词:字符串分词后,不会出现重叠。即"ilovechina",不同词库可分割为"i,love,china","ilove,china",不能分割出现重叠的"i,ilove,china",i 出现重叠
标点符号不成词,仅用于断句
词库:根据外部知识库统计出来的常用词汇例:dictionary = ["i", "love", "china", "lovechina", "ilove"]
分词原则:采用分词顺序优先且最长匹配原则 "ilovechina",假设分词结果 [i,ilove,lo,love,ch,china,lovechina],则输出 [ilove,china] 错误输出:[i,lovechina],原因:"ilove" > 优先于 "lovechina" 成词 错误输出:[i,love,china],原因:"ilove" > "i"遵循最长匹配原则
输入描述
第一行输入待分词语句 "ilovechina",字符串长度限制:0 < length < 256
第二行输入中文词库
"i,love,china,ch,na,ve,lo,this,is,this,word",词库长度限制:1 < length < 100000
输出描述
按顺序输出分词结果 "i,love,china"
用例
输入
ilovechina
i,love,china,ch,na,ve,lo,this,is,the,word
输出
i,love,china
#include <iostream>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <queue>
#include <algorithm>
using namespace std;
vector<string> split(const string& str, const string& delimiters) {
vector<string> tokens;
size_t prev = 0, pos = 0;
do {
pos = str.find_first_of(delimiters, prev);
if (pos == string::npos) pos = str.length();
string token = str.substr(prev, pos - prev);
if (!token.empty()) tokens.push_back(token);
prev = pos + 1;
} while (pos < str.length() && prev < str.length());
return tokens;
}
string join(const vector<string>& words, const string& delimiter) {
ostringstream os;
for (size_t i = 0; i < words.size(); ++i) {
if (i != 0) os << delimiter;
os << words[i];
}
return os.str();
}
vector<string> segmentSentence(const string& sentence, unordered_set<string>& dictionary) {
vector<string> result;
int n = sentence.length();
int i = 0;
while (i < n) {
bool matched = false;
for (int len = n - i; len > 0; len--) {
string substring = sentence.substr(i, len);
if (dictionary.find(substring) != dictionary.end()) {
result.push_back(substring);
dictionary.erase(substring); // 假设每个词汇只能使用一次
i += len;
matched = true;
break;
}
}
if (!matched) {
result.push_back(string(1, sentence[i]));
i++;
}
}
return result;
}
int main() {
string sentenceInput, wordsInput;
getline(cin, sentenceInput);
getline(cin, wordsInput);
vector<string> sentences = split(sentenceInput, ",.;");
vector<string> words = split(wordsInput, ",");
unordered_set<string> dictionary(words.begin(), words.end());
queue<string> sentencesQueue;
for (const string& s : sentences) {
sentencesQueue.push(s);
}
vector<string> result;
while (!sentencesQueue.empty()) {
string sentence = sentencesQueue.front();
sentencesQueue.pop();
vector<string> segmented = segmentSentence(sentence, dictionary);
result.insert(result.end(), segmented.begin(), segmented.end());
}
cout << join(result, ",") << endl;
return 0;
}
6 园区参观路径计算
题目
园区某部门举办了Family Day,邀请员工及其家属参加; 将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角; 家属参观园区时,只能向右和向下园区前进,求从起始园区到终点园区会有多少条不同的参观路径。
输入描述
第一行为园区的长和宽;
后面每一行表示该园区是否可以参观,0表示可以参观,1表示不能参观
输出描述
输出为不同的路径数量
用例
输入
3 3
0 0 0
0 1 0
0 0 0
输出
2
Copy
解题思路
创建一个二维数组 dp 来记录到达每个位置的路径数,初始化起点的路径数为1。对于每个可以参观的位置,路径数等于从上方和左方到达的路径数之和。通过逐行逐列地填充 dp 数组,最终在终点位置获得从起点到终点的所有不同路径数量。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int rows, cols;
cin >> rows >> cols;
vector<vector<int>> park(rows, vector<int>(cols));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cin >> park[i][j];
}
}
vector<vector<int>> dp(rows, vector<int>(cols, 0));
if (park[0][0] == 0) {
dp[0][0] = 1;
}
for (int i = 1; i < rows; ++i) {
if (park[i][0] == 0) {
dp[i][0] = dp[i-1][0];
}
}
for (int j = 1; j < cols; ++j) {
if (park[0][j] == 0) {
dp[0][j] = dp[0][j-1];
}
}
for (int i = 1; i < rows; ++i) {
for (int j = 1; j < cols; ++j) {
if (park[i][j] == 0) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
cout << dp[rows-1][cols-1] << endl;
return 0;
}
7 需求开发人力安排(超时)
题目
部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。 这部分需求需要在 M 个月内完成开发,进行人力安排后每个月人力时固定的。 目前要求每个月最多有2个需求开发,并且每个月需要完成的需求不能超过部门人力。 请帮助部门评估在满足需求开发进度的情况下,每个月需要的最小人力是多少?
输入描述
输入为 M 和 requirements,M 表示需求开发时间要求,requirements 表示每个需求工作量大小,N 为 requirements长度,
1 ≤ N/2 ≤ M ≤ N ≤ 10000
1 ≤ requirements[i] ≤ 10^9
输出描述
对于每一组测试数据,输出部门需要人力需求,行末无多余的空格
用例
输入
3
3 5 3 4
输出
6
Copy
解题思路
首先对任务工作量数组进行排序,然后使用二分查找法确定每月所需的最小人力上限。在二分查找过程中,计算中间值作为当前的尝试容量,并使用双指针法判断在此容量下是否能在限定月份内完成所有任务。分别检查最轻和最重的任务是否可以在同一个月内完成,逐步更新任务指针和所需的月份数。如果在限定月份内可以完成任务,则缩小搜索范围;否则,扩大搜索范围。最终确定最小人力上限即为结果。
#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
bool canCompleteWithinMonths(long capacity, int months, const vector<int>& tasks) {
int left = 0;
int right = tasks.size() - 1;
int requiredMonths = 0;
while (left <= right) {
if (tasks[left] + tasks[right] <= capacity) {
left++;
}
right--;
requiredMonths++;
}
return requiredMonths <= months;
}
long calculateMidCapacity(long minCapacity, long maxCapacity) {
return (minCapacity + maxCapacity) / 2;
}
long findMinimumCapacity(int months, vector<int>& tasks) {
sort(tasks.begin(), tasks.end());
if (tasks.size() == 1) {
return tasks[0];
}
long minCapacity = tasks[tasks.size() - 1];
long maxCapacity = tasks[tasks.size() - 2] + tasks[tasks.size() - 1];
long optimalCapacity = maxCapacity;
while (minCapacity <= maxCapacity) {
long midCapacity = calculateMidCapacity(minCapacity, maxCapacity);
if (canCompleteWithinMonths(midCapacity, months, tasks)) {
optimalCapacity = midCapacity;
maxCapacity = midCapacity - 1;
} else {
minCapacity = midCapacity + 1;
}
}
return optimalCapacity;
}
int main() {
int months;
cin >> months;
cin.ignore();
string line;
getline(cin, line);
istringstream iss(line);
vector<int> tasks;
int task;
while (iss >> task) {
tasks.push_back(task);
}
cout << findMinimumCapacity(months, tasks) << endl;
return 0;
}
8 单人卡牌游戏的最优出牌策略
题目
有这么一款单人卡牌游戏,牌面由颜色和数字组成,颜色为红、黄、蓝、绿中的一种,数字为0-9中的一个。游戏开始时玩家从手牌中选取一张卡牌打出,接下来如果玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌,他可以继续将该手牌打出,直至手牌打光或者没有符合条件可以继续打出的手牌。 现给定一副手牌,请找到最优的出牌策略,使打出的手牌最多。
输入描述
输入为两行
第一行是每张手牌的数字,数字由空格分隔, 第二行为对应的每张手牌的颜色,用r y b g这4个字母分别代表4种颜色,字母也由空格分隔。 手牌数量不超过10。
输出描述
输出一个数字,即最多能打出的手牌的数量。
用例
输入
1 4 3 4 5
r y b b r
输出
3
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
struct Card {
int number;
char color;
Card(int n, char c) : number(n), color(c) {}
};
int dfs(vector<Card>& cards, vector<bool>& visited, int n, int index) {
visited[index] = true;
int maxCount = 1;
for (int i = 0; i < n; ++i) {
if (!visited[i] && (cards[i].number == cards[index].number || cards[i].color == cards[index].color)) {
maxCount = max(maxCount, 1 + dfs(cards, visited, n, i));
}
}
visited[index] = false;
return maxCount;
}
int maxCards(string numbers, string colors) {
stringstream ss_nums(numbers);
stringstream ss_cols(colors);
vector<int> nums;
vector<char> cols;
int num;
char col;
while (ss_nums >> num) {
nums.push_back(num);
}
while (ss_cols >> col) {
cols.push_back(col);
}
int n = nums.size();
vector<Card> cards;
for (int i = 0; i < n; ++i) {
cards.emplace_back(nums[i], cols[i]);
}
vector<bool> visited(n, false);
int maxCount = 0;
for (int i = 0; i < n; ++i) {
maxCount = max(maxCount, dfs(cards, visited, n, i));
}
return maxCount;
}
int main() {
string numbers;
string colors;
getline(cin, numbers);
getline(cin, colors);
cout << maxCards(numbers, colors) << endl;
return 0;
}
9 5G基站最小连接成本计算
题目
现需要在某城市进行5G网络建设,已经选取N个地点设置5G基站,编号固定为1到N,接下来需要各个基站之间使用光纤进行连接以确保基站能互联互通,不同基站之间假设光纤的成本各不相同,且有些节点之间已经存在光纤相连。
请你设计算法,计算出能联通这些基站的最小成本是多少。
注意:基站的联通具有传递性,比如基站A与基站B架设了光纤,基站B与基站C也架设了光纤,则基站A与基站C视为可以互相联通。
输入描述
第一行输入表示基站的个数N,其中:0 < N ≤ 20 第二行输入表示具备光纤直连条件的基站对的数目M,其中:0 < M < N * (N - 1) / 2 从第三行开始连续输入M行数据,格式为X Y Z P 其中:
X,Y 表示基站的编号
0 < X ≤ N
0 < Y ≤ N
X ≠ Y
Z 表示在 X、Y之间架设光纤的成本
0 < Z < 100
P 表示是否已存在光纤连接,0 表示未连接,1表示已连接
输出描述
如果给定条件,可以建设成功互联互通的5G网络,则输出最小的建设成本 如果给定条件,无法建设成功互联互通的5G网络,则输出 -1
用例
输入
3
3
1 2 3 0
1 3 1 0
2 3 5 0
输出
4
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge {
int x, y, cost, connected;
bool operator<(const Edge& other) const {
return cost < other.cost;
}
};
int find(vector<int>& parent, int i) {
if (parent[i] != i) {
parent[i] = find(parent, parent[i]);
}
return parent[i];
}
void unionSets(vector<int>& parent, vector<int>& rank, int x, int y) {
int rootX = find(parent, x);
int rootY = find(parent, y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
int main() {
int N, M;
cin >> N >> M;
vector<Edge> edges(M);
for (int i = 0; i < M; i++) {
cin >> edges[i].x >> edges[i].y >> edges[i].cost >> edges[i].connected;
}
sort(edges.begin(), edges.end());
vector<int> parent(N + 1);
vector<int> rank(N + 1, 0);
for (int i = 1; i <= N; i++) {
parent[i] = i;
}
int totalCost = 0;
int edgesUsed = 0;
// 处理已连接的边
for (const auto& edge : edges) {
if (edge.connected == 1) {
int rootX = find(parent, edge.x);
int rootY = find(parent, edge.y);
if (rootX != rootY) {
unionSets(parent, rank, edge.x, edge.y);
edgesUsed++;
}
}
}
// 处理未连接的边
for (const auto& edge : edges) {
if (edge.connected == 0) {
int rootX = find(parent, edge.x);
int rootY = find(parent, edge.y);
if (rootX != rootY) {
unionSets(parent, rank, edge.x, edge.y);
totalCost += edge.cost;
edgesUsed++;
}
}
}
if (edgesUsed == N - 1) {
cout << totalCost << endl;
} else {
cout << -1 << endl;
}
return 0;
}
10 孙悟空吃蟠桃的最小速度(输出有误)
题目
孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有 N 棵桃树,每颗树上都有桃子,守卫将在 H 小时后回来。孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉 K 个,如果树上的桃子少于 K 个,则全部吃掉,并且这一小时剩余的时间里不再吃桃。孙悟空喜欢慢慢吃,但又想在守卫回来前吃完桃子。 请返回孙悟空可以在 H 小时内吃掉所有桃子的最小速度 K(K为整数)。如果以任何速度都吃不完所有桃子,则返回0。
输入描述
第一行输入为 N 个数字,N 表示桃树的数量,这 N 个数字表示每颗桃树上蟠桃的数量。 第二行输入为一个数字,表示守卫离开的时间 H。 其中数字通过空格分割,N、H为正整数,每颗树上都有蟠桃,且 0 < N < 10000,0 < H < 10000。
输出描述
吃掉所有蟠桃的最小速度 K,无解或输入异常时输出 0。
用例
输入
2 3 4 5
4
输出
5
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
bool canEatAllPeaches(const std::vector<int>& peaches, int H, int K) {
int hoursNeeded = 0;
for (int peach : peaches) {
hoursNeeded += (peach + K - 1) / K; // 向上取整 (peach / K)
}
return hoursNeeded <= H;
}
int minEatingSpeed(const std::vector<int>& peaches, int H) {
int maxPeaches = *std::max_element(peaches.begin(), peaches.end());
int left = 1, right = maxPeaches;
int result = 0;
while (left <= right) {
int mid = left + (right - left) / 2;
if (canEatAllPeaches(peaches, H, mid)) {
result = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return result;
}
int main() {
std::vector<int> peaches;
int num, H;
while (std::cin >> num) {
peaches.push_back(num);
if (std::cin.get() == '\n') break;
}
std::cin >> H;
std::cout << minEatingSpeed(peaches, H) << std::endl;
return 0;
}

浙公网安备 33010602011771号