枚举经典例题
1 UVA725 除法
问题:输入正整数
// 输入
62
// 输出
79546 / 01283 = 62
94736 / 01528 = 62分析:如果我们选择枚举
2 UVA11059 最大乘积
问题:输入
// 输入
3
2 4 -3
// 输出
8
// 输入
5
2 5 -1 2 -1
// 输出
20分析:枚举连续子序列的起点和终点,计算最大值。由于每个元素的绝对值不超过 long long 存储。
3 分数拆分
问题:输入正整数
// 输入
2
// 输出
2
1/2 = 1/6 + 1/3
1/2 = 1/4 + 1/4分析:由于
4 火柴棒等式
给你

注意:
- 加号与等号各自需要两根火柴棍;
- 如果
,则 与 视为不同的等式( ); 根火柴棍必须全部用上。
14
2// 输入
18
// 输出
9总结反思
枚举算法本质上就是假设出更多的条件,把原问题从复杂转换成简单,方便我们设计算法求解。
举例:给定一个整数
样例输入:
105样例输出:
1 4 10
4 8 9
7 7 7分析:我们只需要枚举
只枚举
为什么选择
枚举专题补充
枚举算法的本质是提供条件,把问题转换为简单的问题。设计枚举算法的核心就是用尽量少的枚举内容,去提供更多的信息,以来简化问题。
举例:现在有
样例输入:
x[1] + x[2] + x[4] = 7
2x[2] + x[3] + 3x[1] = 10
x[3] + x[4] - x[2] = 5
x[4] + 2x[1] + x[3] = 9样例输出:
x[1] = 1
x[2] = 2
x[3] = 3
x[4] = 4分析:很自然的我们会想到依次枚举
换一种思路,我们尝试枚举
可以继续优化吗?只枚举一个值,假设为
具体如下:假设
带入第一个方程:
带入第二个方程:
带入第三个方程:
此时利用第四个方程
更进一步,什么都不枚举,直接带入变量形式。
带入第一个方程:
带入第二个方程:
联立最后两个方程,求解即可。
双指针算法
对于一些问题,我们需要枚举变量
例如,一些题目问:最小找到一个多长的区间
for (int i = 1; i <= n; i++) {
for (int j = x; j <= n; j++) {
if (is_ok(x, y)) {
ans[x] = y;
break;
}
}
}双指针实现:
int y = 1;
for (int i = 1; i <= n; i++) {
while (!is_ok(x, y) && y <= n) y++;
if (is_ok(x, y)) ans[x] = y;
}还记得奶牛的舞会这道题吗?
有
我们可以使用双指针解决它。
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
int L[N];
int main() {
int n, s;
cin >> n >> s;
for(int i = 0; i < n; i++) cin >> L[i];
sort(L, L + n);
int res = 0;
int i = 0, j = n - 1;
while (i < j) {
if (L[i] + L[j] <= s) {
res += j - i;
i++;
}
else {
j--;
}
}
cout << res << endl;
return 0;
}课后习题
问题 #1
有一个长度为
问题 #2
有一个长度为
问题 #3
校门外有连续的
问题 #4
给你一个大小为
问题 #5
给你 * 代替,例如:
15*
1*0
1**
1*1*
1**1已知这
问题 #6
有
