模拟算法概述
枚举是模拟算法的核心,本质就是把所有可能的情况罗列出来,筛选出符合题意的那一个。虽然暴力枚举容易超时,但在数据范围允许的情况下,它是最直接的解法。如果直接枚举会超时,就需要结合题目特性优化枚举顺序或对象(比如二分、双指针等)。思考重点在于:枚举什么?按什么顺序?怎么枚举?
经典例题解析
1. 铺地毯
问题描述:给定 n 张地毯的坐标和长宽,查询某个点被哪张最后铺设的地毯覆盖。
思路: 我们需要找到覆盖该点的最后一张地毯。如果正序遍历,必须检查完所有地毯才能确定结果;如果逆序遍历,一旦找到第一张覆盖的点,就是答案,可以直接返回。这种优化能显著减少不必要的判断。
代码实现:
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL a[N], b[N], g[N], k[N]; // x, y, width, height
int n;
int find(int x, int y) {
for (int i = n; i >= 1; i--) {
if (x >= a[i] && y >= b[i] && x <= a[i] + g[i] && y <= b[i] + k[i]) {
return i;
}
}
return -1;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i] >> b[i] >> g[i] >> k[i];
LL x, y;
cin >> x >> y;
cout << find(x, y) << endl;
return 0;
}
2. 回文日期
问题描述:在给定日期范围内,统计有多少个日期是回文的。
思路: 回文日期的特点是年份由月日决定,或者月日由年份决定。 策略一:枚举月日组合,反推年份。复杂度 O(12*31),效率最高。注意闰年 2 月只有 29 天。 策略二:枚举年份,反推月日。复杂度 O(年份差),稍慢但逻辑直观。


