作为信息学竞赛的经典入门题目,矩形面积计算问题一直是考察学生基础几何思维和编程实现能力的试金石。今天我们要深入剖析的是USACO 2017年12月青铜组的Blocked Billboard问题,这道题看似简单,却蕴含着许多值得初学者注意的编程技巧和算法思维。
题目描述了一个生动有趣的场景:奶牛Bessie喜欢透过谷仓窗户观看街对面的两块矩形广告牌。某天,一辆矩形卡车停在了广告牌前,可能会遮挡部分广告牌。我们的任务是计算两块广告牌仍然可见的总面积。
这个场景实际上抽象出了一个经典的几何问题:计算多个矩形在平面上的可见区域。这类问题在实际应用中非常广泛,比如图形界面中的窗口遮挡处理、游戏开发中的碰撞检测等。
输入包含三行,每行四个整数:
所有坐标值范围在[-1000,1000]之间,且保证两块广告牌没有重叠区域。
输出要求:一个整数,表示两块广告牌未被卡车遮挡的总面积。
以题目给出的样例为例:
code复制1 2 3 5
6 0 10 4
2 1 8 3
通过可视化分析可以发现:
最直观的解法是利用矩形相交面积的计算公式。对于两个矩形A和B,它们的重叠区域可以通过以下方式确定:
如果右边界>左边界且上边界>下边界,则存在有效重叠区域,面积为:
(右-左)*(上-下)
实现步骤:
另一种更通用的方法是离散化处理,特别适合复杂的不规则重叠情况。基本思路:
这种方法虽然计算量稍大,但可以处理更复杂的几何形状,是计算几何中的常用技术。
cpp复制#include <bits/stdc++.h>
using namespace std;
int a[5], b[5], c[5]; // 存储三个矩形的坐标
int ans = 0; // 存储未被覆盖的总面积
int x[7], y[7]; // 存储所有x和y坐标
bool in(int i, int j, int k[]) {
// 检查网格是否完全在矩形内
return x[i] >= k[1] && x[i+1] <= k[3] &&
y[j] >= k[2] && y[j+1] <= k[4];
}
int main() {
// 输入三个矩形的坐标
for(int i=1;i<=4;i++) cin>>a[i];
for(int i=1;i<=4;i++) cin>>b[i];
for(int i=1;i<=4;i++) cin>>c[i];
// 收集所有x和y坐标
x[1]=a[1]; x[2]=a[3]; x[3]=b[1]; x[4]=b[3]; x[5]=c[1]; x[6]=c[3];
y[1]=a[2]; y[2]=a[4]; y[3]=b[2]; y[4]=b[4]; y[5]=c[2]; y[6]=c[4];
// 坐标排序
sort(x+1,x+7);
sort(y+1,y+7);
// 遍历所有网格
for(int i=1;i<=5;i++) {
for(int j=1;j<=5;j++) {
// 检查是否在广告牌但不在卡车内
if((in(i,j,a)&&!in(i,j,c)) || (in(i,j,b)&&!in(i,j,c))) {
ans += (y[j+1]-y[j])*(x[i+1]-x[i]);
}
}
}
cout<<ans<<endl;
return 0;
}
cpp复制#include <bits/stdc++.h>
using namespace std;
struct Rect { int x1,y1,x2,y2; };
int area(Rect r) {
return (r.x2-r.x1)*(r.y2-r.y1);
}
int overlap(Rect a, Rect b) {
int xOver = max(0, min(a.x2,b.x2) - max(a.x1,b.x1));
int yOver = max(0, min(a.y2,b.y2) - max(a.y1,b.y1));
return xOver * yOver;
}
int main() {
Rect b1, b2, truck;
cin >> b1.x1 >> b1.y1 >> b1.x2 >> b1.y2;
cin >> b2.x1 >> b2.y1 >> b2.x2 >> b2.y2;
cin >> truck.x1 >> truck.y1 >> truck.x2 >> truck.y2;
int visible = area(b1) + area(b2)
- overlap(b1, truck)
- overlap(b2, truck);
cout << visible << endl;
return 0;
}
在实际编码中,需要特别注意以下几种边界情况:
对于USACO青铜组题目,推荐使用更直观的数学方法:
离散化方法虽然更通用,但:
初学者常犯的错误包括:
调试建议:
数学方法:
离散化方法:
两种方法都只使用了固定大小的数组,空间复杂度O(1)
这个问题可以有多种变体:
对于更复杂的情况,可以考虑:
这道Blocked Billboard问题虽然属于USACO青铜组,但它很好地训练了参赛者的几何思维和编程实现能力。通过这个问题,我们学习了矩形相交面积的计算方法,掌握了处理几何问题的基本思路,这些技能在更高难度的竞赛题目中也会经常用到。建议初学者在理解本题的基础上,尝试解决类似的矩形覆盖问题,如洛谷P1885、P2201等题目,逐步提升自己的几何问题解决能力。