111

考点一:基础输入输出与模拟(难度:签到题 ★☆☆☆☆)

题目特征:题目描述较长,像是叙述一个过程或规则。不需要复杂算法,严格按照题意一步步实现即可。常见于第1、2题。

核心思想:仔细读题,注意边界条件。多用cout进行调试,输出中间变量。

必背模板:多组输入输出处理(这是ACM考题的标配)。

#include <iostream>

using namespace std;

int main() {

int t; // 测试组数

cin >> t;

while (t--) { // 处理t组数据

int n;

cin >> n;

int arr[1000]; // 假设最多1000个元素

for (int i = 0; i < n; i++) {

cin >> arr[i];

}

// 你的处理代码...

cout << "结果" << endl; // 输出结果

}

return 0;

}考点二:排序与查找(难度:简单 ★★☆☆☆)

题目特征:对一组数据排序后输出、求第K大/小的数、在有序数组中查找某个值的位置。

核心思想:直接用STL sort/lower_bound。

必背模板:

1.冒泡排序

#include <iostream>

using namespace std;

void bubbleSort(int arr[], int n) {

for (int i = 0; i < n-1; i++) {

for (int j = 0; j < n-1-i; j++) {

if (arr[j] > arr[j+1]) {

// 交换

int temp = arr[j];

arr[j] = arr[j+1];

arr[j+1] = temp;

}

}

}

}

int main() {

int n;

cin >> n;

int arr[1000];

for (int i = 0; i < n; i++) {

cin >> arr[i];

}

// 排序

bubbleSort(arr, n);

// 输出结果

for (int i = 0; i < n; i++) {

cout << arr[i] << " ";

}

cout << endl;

return 0;

}

2.查找最大/最小值 #include <iostream>

using namespace std;

int main() {

int n;

cin >> n;

int arr[1000];

for (int i = 0; i < n; i++) {

cin >> arr[i];

}

// 找最大值

int maxVal = arr[0];

for (int i = 1; i < n; i++) {

if (arr[i] > maxVal) {

maxVal = arr[i];

}

}

// 找最小值

int minVal = arr[0];

for (int i = 1; i < n; i++) {

if (arr[i] < minVal) {

minVal = arr[i];

}

}

cout << "最大值: " << maxVal << endl;

cout << "最小值: " << minVal << endl;

return 0;

}

3.二分查找

#include <iostream>

using namespace std;

int main() {

int n, target;

cin >> n >> target;

int arr[1000];

for (int i = 0; i < n; i++) {

cin >> arr[i];

}

int left = 0, right = n-1;

bool found = false;

while (left <= right) {

int mid = (left + right) / 2;

if (arr[mid] == target) {

cout << "找到,位置: " << mid << endl;

found = true;

break;

} else if (arr[mid] < target) {

left = mid + 1;

} else {

right = mid - 1;

}

}

if (!found) {

cout << "未找到" << endl;

}

return 0;

}

考点三:贪心算法(难度:中等 ★★★☆☆)

题目特征:问题可以分解成一系列步骤,每一步都采取当前状态下最优选择(局部最优),从而希望导致全局最优。常考:区间调度、简单背包、哈夫曼编码(合并果子)。

核心思想:先排序,再贪心。关键是证明(考试时想不出就直接写,有步骤分)。

必背模板:活动选择(简化版)

#include <iostream>

using namespace std;

int main() {

int n; // 活动数量

cin >> n;

int start[1000], end[1000];

for (int i = 0; i < n; i++) {

cin >> start[i] >> end[i];

}

// 按结束时间排序(用冒泡排序)

for (int i = 0; i < n-1; i++) {

for (int j = 0; j < n-1-i; j++) {

if (end[j] > end[j+1]) {

// 交换结束时间

int temp = end[j];

end[j] = end[j+1];

end[j+1] = temp;

// 同时交换开始时间

temp = start[j];

start[j] = start[j+1];

start[j+1] = temp;

}

}

}

// 贪心选择

int count = 1; // 至少能安排一个活动

int lastEnd = end[0];

for (int i = 1; i < n; i++) {

if (start[i] >= lastEnd) {

count++;

lastEnd = end[i];

}

}

cout << count << endl;

return 0;

考点四:动态规划 - 经典线性DP(难度:中上 ★★★★☆)

题目特征:求“最值”、“总数”、“是否可行”。问题可以被分解为重叠的子问题。目录中第9章就是动态规划。

核心思想:定义 dp[i]或 dp[i][j]数组的含义 -> 找出状态转移方程 -> 确定初始值 -> 计算顺序。

必背模板1:斐波那契/爬楼梯(入门理解)

#include <iostream>

using namespace std;

int main() {

int n;

cin >> n;

int dp[1000]; // dp[i]表示第i个斐波那契数

dp[0] = 1;

dp[1] = 1;

for (int i = 2; i <= n; i++) {

dp[i] = dp[i-1] + dp[i-2];

}

cout << dp[n] << endl;

return 0;

}

必背模板2:简单路径

#include <iostream>

using namespace std;

int main() {

int n, m; // n行m列的网格

cin >> n >> m;

int dp[100][100]; // dp[i][j]表示到达(i,j)的路径数

// 初始化第一行和第一列

for (int i = 0; i < n; i++) dp[i][0] = 1;

for (int j = 0; j < m; j++) dp[0][j] = 1;

// 计算其他位置

for (int i = 1; i < n; i++) {

for (int j = 1; j < m; j++) {

dp[i][j] = dp[i-1][j] + dp[i][j-1];

}

}

cout << dp[n-1][m-1] << endl;

return 0;

}

必背模板3:简单背包问题(贪心版)

#include <iostream>

using namespace std;

int main() {

int n, capacity; // n个物品,背包容量

cin >> n >> capacity;

int weight[1000], value[1000];

for (int i = 0; i < n; i++) {

cin >> weight[i] >> value[i];

}

// 计算性价比(价值/重量)并排序

double ratio[1000];

int index[1000];

for (int i = 0; i < n; i++) {

ratio[i] = (double)value[i] / weight[i];

index[i] = i;

}

// 按性价比排序(降序)

for (int i = 0; i < n-1; i++) {

for (int j = 0; j < n-1-i; j++) {

if (ratio[j] < ratio[j+1]) {

// 交换ratio

double tempRatio = ratio[j];

ratio[j] = ratio[j+1];

ratio[j+1] = tempRatio;

// 交换index

int tempIndex = index[j];

index[j] = index[j+1];

index[j+1] = tempIndex;

}

}

}

// 贪心选择

int currentWeight = 0;

double totalValue = 0.0;

for (int i = 0; i < n; i++) {

int idx = index[i];

if (currentWeight + weight[idx] <= capacity) {

currentWeight += weight[idx];

totalValue += value[idx];

}

}

cout << "最大价值: " << totalValue << endl;

return 0;

}}

考点五:并查集(难度:中等 ★★★☆☆)

题目特征:题目中出现“朋友的朋友是朋友”、“连通性”、“分组”、“合并集合”等关键词。目录第10章就是并查集。

核心思想:维护一个father数组,实现find(查找根节点+路径压缩)和merge(合并集合)两个函数。

必背模板:

#include <iostream>

using namespace std;

int father[1000]; // 假设最多1000个元素

// 初始化

void init(int n) {

for (int i = 1; i <= n; i++) {

father[i] = i;

}

}

// 查找(递归版本,带路径压缩)

int find(int x) {

if (father[x] != x) {

father[x] = find(father[x]);

}

return father[x];

}

// 合并

void merge(int a, int b) {

int rootA = find(a);

int rootB = find(b);

if (rootA != rootB) {

father[rootA] = rootB;

}

}

int main() {

int n, m; // n个元素,m个操作

cin >> n >> m;

init(n);

for (int i = 0; i < m; i++) {

int op, a, b;

cin >> op >> a >> b;

if (op == 1) { // 合并操作

merge(a, b);

} else if (op == 2) { // 查询操作

if (find(a) == find(b)) {

cout << "YES" << endl;

} else {

cout << "NO" << endl;

}

}

}

return 0;

}

补充:

判断素数

#include <iostream>

#include <cmath>

using namespace std;

bool isPrime(int n) {

if (n <= 1) return false;

for (int i = 2; i <= sqrt(n); i++) {

if (n % i == 0) return false;

}

return true;

}

int main() {

int n;

cin >> n;

if (isPrime(n)) {

cout << n << " 是素数" << endl;

} else {

cout << n << " 不是素数" << endl;

}

return 0;

}

求最大公约数(欧几里得算法)

#include <iostream>

using namespace std;

int gcd(int a, int b) {

while (b != 0) {

int temp = a % b;

a = b;

b = temp;

}

return a;

}

int main() {

int a, b;

cin >> a >> b;

cout << gcd(a, b) << endl;

return 0;

}

简单递归:阶乘计算

#include <iostream>

using namespace std;

int factorial(int n) {

if (n <= 1) {

return 1;

}

return n * factorial(n-1);

}

int main() {

int n;

cin >> n;

cout << factorial(n) << endl;

return 0;

}

字符串处理(统计字符):

#include <iostream>

#include <cstring> // 使用strlen函数

using namespace std;

int main() {

char str[1000];

cin >> str; // 或 cin.getline(str, 1000) 读取整行

int len = strlen(str);

int letter = 0, digit = 0, other = 0;

for (int i = 0; i < len; i++) {

if ((str[i] >= 'a' && str[i] <= 'z') ||

(str[i] >= 'A' && str[i] <= 'Z')) {

letter++;

} else if (str[i] >= '0' && str[i] <= '9') {

digit++;

} else {

other++;

}

}

cout << "字母: " << letter << endl;

cout << "数字: " << digit << endl;

cout << "其他: " << other << endl;

return 0;

}

考场快速索引指南

1、读题后,快速判断类型:

问“怎么安排最多” -> 先想贪心(排序+遍历)。

问“最大价值/最小代价/有多少种方法” -> 先想动态规划(背包、线性DP)。

问“是否连通/是否同一组” -> 直接上并查集模板。

题目描述就是步骤 -> 模拟,小心实现。

需要先排序或找位置 -> 直接用STL sort/lower_bound。

2、写代码的步骤:

1.第一步:写好头文件#include <bits/stdc++.h>和using namespace std;(竞赛万能头,节省时间)。

2.第二步:根据判断的类型,把对应数据结构的定义和核心函数先抄上去(比如dp数组定义,并查集类)。

3.第三步:再根据题目具体要求,修改main函数里的输入输出和逻辑细节。

考试策略

先看输入输出格式:严格按照题目要求的格式

判断问题类型:

排序 → 用冒泡排序

找最大/最小 → 遍历比较

计数/统计 → 遍历累加

路径/组合 → 考虑动态规划

最优选择 → 考虑贪心

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务