CSP-J/S考试大纲知识点
文章标题:CSP-J/S考试大纲知识点分类名称知识点编程入门程序的基本结构main函数、输入输出语句、Dev C++的使用变量和常量变量
2025-12-09
以下是15道完整的信奥赛C++算法题,每道题包含题目描述、输入输出格式、样例和C++参考代码。这里15题精选涵盖各核心算法类型的代表性题目。
题目描述:给定一个整数,请将该数各个位上数字反转得到一个新数。新数不应有前导零。
输入格式:一个整数 N(-1,000,000,000 ≤ N ≤ 1,000,000,000)
输出格式:反转后的新数
样例输入:
text
-380
样例输出:
text
-83
C++代码:
cpp
#include <iostream>#include <string>#include <algorithm>using namespace std;int main() {
int n;
cin >> n;
string s = to_string(abs(n)); // 转为字符串并取绝对值
std::reverse(s.begin(), s.end()); // 反转字符串
// 去除前导零
int i = 0;
while (i < s.length() - 1 && s[i] == '0') {
i++;
}
s = s.substr(i);
// 输出结果
if (n < 0) {
cout << "-";
}
cout << s << endl;
return 0;}题目描述:陶陶有一张30cm高的凳子,当她不能直接用手摘到苹果时,会站到凳子上再试试。现在已知10个苹果到地面的高度,以及陶陶把手伸直能够到的最大高度,请帮她算一下她能够摘到的苹果数目。
输入格式:
第一行:10个整数,表示苹果到地面的高度
第二行:一个整数,表示陶陶把手伸直能够到的最大高度
输出格式:一个整数,表示陶陶能够摘到的苹果数目
样例输入:
text
100 200 150 140 129 134 167 198 200 111 110
样例输出:
text
5
C++代码:
cpp
#include <iostream>using namespace std;int main() {
int apples[10];
for (int i = 0; i < 10; i++) {
cin >> apples[i];
}
int tao_height;
cin >> tao_height;
int chair_height = 30;
int total_height = tao_height + chair_height;
int count = 0;
for (int i = 0; i < 10; i++) {
if (apples[i] <= total_height) {
count++;
}
}
cout << count << endl;
return 0;}题目描述:有n件物品和一个容量为C的背包。第i件物品的重量是w_i,价值是v_i。你可以选择物品的一部分放入背包,其价值按重量比例计算。问背包能装入的最大总价值。
输入格式:
第一行:两个整数n和C
接下来n行:每行两个整数w_i, v_i
输出格式:一个浮点数,表示最大总价值,精确到小数点后两位
样例输入:
text
3 50 10 60 20 100 30 120
样例输出:
text
240.00
C++代码:
cpp
#include <iostream>#include <iomanip>#include <algorithm>#include <vector>using namespace std;struct Item {
int weight;
int value;
double value_per_weight;};bool compare(Item a, Item b) {
return a.value_per_weight > b.value_per_weight;}int main() {
int n, C;
cin >> n >> C;
vector<Item> items(n);
for (int i = 0; i < n; i++) {
cin >> items[i].weight >> items[i].value;
items[i].value_per_weight = (double)items[i].value / items[i].weight;
}
// 按单位重量价值降序排序
sort(items.begin(), items.end(), compare);
double total_value = 0.0;
int remaining_capacity = C;
for (int i = 0; i < n && remaining_capacity > 0; i++) {
if (items[i].weight <= remaining_capacity) {
// 全部装入
total_value += items[i].value;
remaining_capacity -= items[i].weight;
} else {
// 装入部分
total_value += items[i].value_per_weight * remaining_capacity;
remaining_capacity = 0;
}
}
cout << fixed << setprecision(2) << total_value << endl;
return 0;}题目描述:有n个人在一个水龙头前排队接水,第i个人接水所需时间为t_i。请安排他们的排队顺序,使得所有人的平均等待时间最小。
输入格式:
第一行:一个整数n
第二行:n个整数,表示t_i
输出格式:
第一行:最优的排队顺序(编号,从1开始)
第二行:最小的平均等待时间(保留两位小数)
样例输入:
text
5 3 1 4 2 5
样例输出:
text
2 4 1 3 5 5.10
C++代码:
cpp
#include <iostream>#include <iomanip>#include <algorithm>#include <vector>using namespace std;struct Person {
int id;
int time;};bool compare(Person a, Person b) {
return a.time < b.time;}int main() {
int n;
cin >> n;
vector<Person> people(n);
for (int i = 0; i < n; i++) {
cin >> people[i].time;
people[i].id = i + 1;
}
// 按接水时间升序排序
sort(people.begin(), people.end(), compare);
// 输出排队顺序
for (int i = 0; i < n; i++) {
cout << people[i].id;
if (i < n - 1) cout << " ";
}
cout << endl;
// 计算总等待时间和平均等待时间
long long total_wait_time = 0;
long long current_wait = 0;
for (int i = 0; i < n - 1; i++) {
current_wait += people[i].time;
total_wait_time += current_wait;
}
double average_wait_time = (double)total_wait_time / n;
cout << fixed << setprecision(2) << average_wait_time << endl;
return 0;}题目描述:输出自然数1到n所有不重复的排列,即n的全排列,按字典序输出。
输入格式:一个整数n(1 ≤ n ≤ 8)
输出格式:所有1~n的全排列,每行一个排列,数字间用空格分隔
样例输入:
text
3
样例输出:
text
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
C++代码:
cpp
#include <iostream>#include <vector>#include <algorithm>using namespace std;vector<vector<int>> result;void backtrack(vector<int>& nums, int start, int n) {
if (start == n) {
result.push_back(nums);
return;
}
for (int i = start; i < n; i++) {
swap(nums[start], nums[i]);
backtrack(nums, start + 1, n);
swap(nums[start], nums[i]); // 回溯
}}int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
nums[i] = i + 1;
}
backtrack(nums, 0, n);
// 按字典序排序
sort(result.begin(), result.end());
// 输出结果
for (const auto& perm : result) {
for (int i = 0; i < n; i++) {
cout << perm[i];
if (i < n - 1) cout << " ";
}
cout << endl;
}
return 0;}题目描述:给定一个N×M的迷宫(1代表墙壁,0代表通路),求从左上角(0,0)到右下角(N-1,M-1)的最短路径步数。只能上下左右移动。
输入格式:
第一行:两个整数N, M
接下来N行:每行M个整数(0或1)
输出格式:一个整数,表示最短路径步数。如果无法到达,输出-1
样例输入:
text
5 5 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0
样例输出:
text
8
C++代码:
cpp
#include <iostream>#include <vector>#include <queue>using namespace std;struct Point {
int x, y, steps;};int bfs(vector<vector<int>>& maze, int N, int M) {
if (maze[0][0] == 1 || maze[N-1][M-1] == 1) {
return -1;
}
vector<vector<bool>> visited(N, vector<bool>(M, false));
queue<Point> q;
// 方向数组:上下左右
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
q.push({0, 0, 0});
visited[0][0] = true;
while (!q.empty()) {
Point current = q.front();
q.pop();
// 到达终点
if (current.x == N-1 && current.y == M-1) {
return current.steps;
}
// 探索四个方向
for (int i = 0; i < 4; i++) {
int nx = current.x + dx[i];
int ny = current.y + dy[i];
if (nx >= 0 && nx < N && ny >= 0 && ny < M &&
!visited[nx][ny] && maze[nx][ny] == 0) {
visited[nx][ny] = true;
q.push({nx, ny, current.steps + 1});
}
}
}
return -1;}int main() {
int N, M;
cin >> N >> M;
vector<vector<int>> maze(N, vector<int>(M));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> maze[i][j];
}
}
int result = bfs(maze, N, M);
cout << result << endl;
return 0;}题目描述:给定一个由数字组成的三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或右下方的结点,一直走到底层,请找出一条路径,使路径上经过的数字之和最大。
输入格式:
第一行:一个整数n,表示三角形的层数
接下来n行:第i行有i个整数
输出格式:一个整数,表示最大和
样例输入:
text
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
样例输出:
text
30
C++代码:
cpp
#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {
int n;
cin >> n;
vector<vector<int>> triangle(n, vector<int>(n, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
cin >> triangle[i][j];
}
}
// 动态规划:从底部向上计算
for (int i = n - 2; i >= 0; i--) {
for (int j = 0; j <= i; j++) {
triangle[i][j] += max(triangle[i+1][j], triangle[i+1][j+1]);
}
}
cout << triangle[0][0] << endl;
return 0;}题目描述:给定一个长度为n的整数序列,求出它的最长上升子序列的长度(严格上升)。
输入格式:
第一行:一个整数n
第二行:n个整数
输出格式:一个整数,表示最长上升子序列的长度
样例输入:
text
7 1 7 3 5 9 4 8
样例输出:
text
4
C++代码:
cpp
#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
// 方法1:动态规划 O(n^2)
vector<int> dp(n, 1); // dp[i]表示以nums[i]结尾的最长上升子序列长度
int max_len = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
max_len = max(max_len, dp[i]);
}
cout << max_len << endl;
return 0;}题目描述:有n件物品和一个容量为C的背包。第i件物品的重量是w_i,价值是v_i。求解将哪些物品装入背包可使这些物品的总重量不超过背包容量,且总价值最大。
输入格式:
第一行:两个整数n和C
接下来n行:每行两个整数w_i, v_i
输出格式:一个整数,表示最大的总价值
样例输入:
text
4 10 2 1 3 3 4 5 7 9
样例输出:
text
12
C++代码:
cpp
#include <iostream>#include <vector>#include <algorithm>using namespace std;int main() {
int n, C;
cin >> n >> C;
vector<int> weight(n), value(n);
for (int i = 0; i < n; i++) {
cin >> weight[i] >> value[i];
}
// 动态规划:dp[i][j]表示前i个物品,容量为j时的最大价值
vector<vector<int>> dp(n + 1, vector<int>(C + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= C; j++) {
// 不选第i个物品
dp[i][j] = dp[i-1][j];
// 如果能选第i个物品
if (j >= weight[i-1]) {
dp[i][j] = max(dp[i][j], dp[i-1][j - weight[i-1]] + value[i-1]);
}
}
}
cout << dp[n][C] << endl;
// 空间优化版本(一维数组)
/*
vector<int> dp(C + 1, 0);
for (int i = 0; i < n; i++) {
for (int j = C; j >= weight[i]; j--) {
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[C] << endl;
*/
return 0;}题目描述:如果两个人是亲戚,那么他们的亲戚也是亲戚。给定n个人和m条亲戚关系,回答q个询问,判断两人是否为亲戚。
输入格式:
第一行:三个整数n, m, q
接下来m行:每行两个整数a, b,表示a和b是亲戚
接下来q行:每行两个整数x, y,询问x和y是否为亲戚
输出格式:对于每个询问,输出一行"Yes"或"No"
样例输入:
text
6 5 3 1 2 1 5 3 4 5 2 1 3 1 4 2 3 5 6
样例输出:
text
Yes Yes No
C++代码:
cpp
#include <iostream>#include <vector>using namespace std;class UnionFind {private:
vector<int> parent;
vector<int> rank;
public:
UnionFind(int n) {
parent.resize(n + 1);
rank.resize(n + 1, 0);
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
void unite(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
// 按秩合并
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
bool isConnected(int x, int y) {
return find(x) == find(y);
}};int main() {
int n, m, q;
cin >> n >> m >> q;
UnionFind uf(n);
// 建立亲戚关系
for (int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
uf.unite(a, b);
}
// 回答询问
for (int i = 0; i < q; i++) {
int x, y;
cin >> x >> y;
if (uf.isConnected(x, y)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;}题目描述:给定一个n个点,m条边的有向图(无向图),边权非负。求从点1到点n的最短路径长度。
输入格式:
第一行:两个整数n, m
接下来m行:每行三个整数u, v, w,表示从u到v有一条权值为w的边
输出格式:一个整数,表示从1到n的最短路径长度。如果不存在,输出-1
样例输入:
text
4 4 1 2 1 2 3 2 3 4 3 1 4 10
样例输出:
text
6
C++代码:
cpp
#include <iostream>#include <vector>#include <queue>#include <climits>using namespace std;struct Edge {
int to;
int weight;};struct Node {
int id;
int dist;
bool operator>(const Node& other) const {
return dist > other.dist;
}};int dijkstra(int n, vector<vector<Edge>>& graph) {
vector<int> dist(n + 1, INT_MAX);
vector<bool> visited(n + 1, false);
dist[1] = 0;
priority_queue<Node, vector<Node>, greater<Node>> pq;
pq.push({1, 0});
while (!pq.empty()) {
Node current = pq.top();
pq.pop();
if (visited[current.id]) continue;
visited[current.id] = true;
for (const Edge& edge : graph[current.id]) {
int newDist = current.dist + edge.weight;
if (newDist < dist[edge.to]) {
dist[edge.to] = newDist;
pq.push({edge.to, newDist});
}
}
}
return (dist[n] == INT_MAX) ? -1 : dist[n];}int main() {
int n, m;
cin >> n >> m;
vector<vector<Edge>> graph(n + 1);
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
graph[u].push_back({v, w});
// 如果是无向图,加上下面这行
// graph[v].push_back({u, w});
}
int result = dijkstra(n, graph);
cout << result << endl;
return 0;}题目描述:给定一个无向图,求其最小生成树的边权之和。
输入格式:
第一行:两个整数n, m
接下来m行:每行三个整数u, v, w,表示点u和点v之间有一条权值为w的边
输出格式:一个整数,表示最小生成树的边权之和。如果图不连通,输出"orz"
样例输入:
text
4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3
样例输出:
text
7
C++代码:
cpp
#include <iostream>#include <vector>#include <algorithm>using namespace std;struct Edge {
int u, v, weight;
bool operator<(const Edge& other) const {
return weight < other.weight;
}};class UnionFind {private:
vector<int> parent;
public:
UnionFind(int n) {
parent.resize(n + 1);
for (int i = 1; i <= n; i++) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
bool unite(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
parent[rootY] = rootX;
return true;
}
return false;
}};int kruskal(int n, vector<Edge>& edges) {
sort(edges.begin(), edges.end());
UnionFind uf(n);
int total_weight = 0;
int edges_used = 0;
for (const Edge& edge : edges) {
if (uf.unite(edge.u, edge.v)) {
total_weight += edge.weight;
edges_used++;
if (edges_used == n - 1) {
break;
}
}
}
if (edges_used == n - 1) {
return total_weight;
} else {
return -1; // 表示图不连通
}}int main() {
int n, m;
cin >> n >> m;
vector<Edge> edges(m);
for (int i = 0; i < m; i++) {
cin >> edges[i].u >> edges[i].v >> edges[i].weight;
}
int result = kruskal(n, edges);
if (result == -1) {
cout << "orz" << endl;
} else {
cout << result << endl;
}
return 0;}题目描述:给定一个长度为n的数组,支持两种操作:
将某个区间内的所有数加上一个值
查询某个区间内所有数的和
输入格式:
第一行:两个整数n, m
第二行:n个整数,表示初始数组
接下来m行:每行一个操作。操作格式为:
1 l r k:表示将区间[l, r]内每个数加上k
2 l r:表示询问区间[l, r]内所有数的和
输出格式:对于每个操作2,输出一行一个整数,表示区间和
样例输入:
text
5 5 1 2 3 4 5 2 1 5 1 1 3 2 2 1 5 1 2 4 1 2 1 4
样例输出:
text
15 21 20
C++代码:
cpp
#include <iostream>#include <vector>using namespace std;class SegmentTree {private:
vector<long long> tree;
vector<long long> lazy;
int n;
void build(const vector<int>& nums, int node, int start, int end) {
if (start == end) {
tree[node] = nums[start];
} else {
int mid = (start + end) / 2;
build(nums, node * 2, start, mid);
build(nums, node * 2 + 1, mid + 1, end);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
}
void push_down(int node, int start, int end) {
if (lazy[node] != 0) {
int mid = (start + end) / 2;
tree[node * 2] += lazy[node] * (mid - start + 1);
tree[node * 2 + 1] += lazy[node] * (end - mid);
lazy[node * 2] += lazy[node];
lazy[node * 2 + 1] += lazy
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭或者错误的内容,欢迎发送邮件至272813839@qq.com举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容或者修正错误的内容。
标签: C++
相关文章
使用工具平台为英飞凌MCU(包括CYT2B73)生成嵌入式C代码,并不是一个单一的操作,而是涉及选择工具链、配置项目、生成代码的系统化工程流程。基于车身控制器和A···
2025-12-06
基于CYT2B73芯片,BCM嵌入式C语言代码如下:一、系统架构总览与代码规模说明首先,你需要理解基于AUTOSAR架构的软件是如何组织的,下图清晰地展示了其分层结构以···
2025-12-06
CYT2B73CADQ0AZEGS 是一款高性能的车规级微控制器(MCU),而不是像车钥匙、雨刮电机这样的独立终端器件。CYT2B73CADQ0AZEGS是作为智能“大脑”,即车身控制模块···
2025-12-06
车门控制系统是现代汽车中最复杂的车身电子模块之一,它集成了安全、舒适、网络通信等多种功能。根据车型定位(经济型、豪华型、智能电动车)和安全要求(QM到AS···
2025-12-06
最新资讯
CSP-J/S考试大纲知识点
英飞凌MCU嵌入式开发工具平台
英飞凌CYT2B73芯片 BCM嵌入式C语言代码
英飞凌CYT2B73CADQ0AZEGS集成控制车门车窗车灯雨刮车钥匙的嵌入式C语言代码
车门MCU嵌入式C语言代码
车灯MCU嵌入式C语言代码
精选16-35道信奥赛C++算法题
精选1-15道完整的信奥赛C++算法题