2021年寒假每日一题,2017~2019年的省赛真题。
本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供。
后面的每日一题,每题发一个新博文,请大家看博客目录:https://blog.csdn.net/weixin_43914593
@
2017省赛A类第10题,最后一题,题目链接:
油漆面积 http://oj.ecustacm.cn/problem.php?id=1324
1、题目描述
平面上有n个矩形,给出每个矩形的坐标。这些矩形可能有重叠。
问这些矩形覆盖的总面积是多少。
数据规模:1<=n<10000,坐标0<= x1,y1,x2,y2 <=10000
资源约定:内存 < 256M;CPU < 2000ms
2、题解
本题是一个经典问题:“矩形面积并”。
首先给出两种暴力法。
(1)先单独求每个矩形的面积,然后把所有矩形的面积加起来,最后减去任意两个矩形的交集。求矩形的交集很花时间,需要两两配对,复杂度(O(n^2))。
(2)另一种更简单的暴力法,是把平面划成单位边长为1(面积也是1)的方格。每读入一个矩形,就把它覆盖的方格标注为已覆盖;对所有矩形都这样处理,最后统计被覆盖的方格数量即可。编码极其简单,但是比上一种方法更慢,且消耗极大的空间。
本题的数据非常弱:矩形数量少,坐标值也不大。用第(2)种暴力法,也能通过。对,就这么干!
3、暴力
#include<bits/stdc++.h>
using namespace std;
bool vis[10001][10001]; //100M内存
int main(){
int n,sum=0; //sum:面积
scanf("%d",&n);
for(int k=0;k<n;k++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2); //读一个矩形
if(x1>x2) swap(x1,x2); //坐标排序
if(y1>y2) swap(y1,y2);
for(int i=x1;i<x2;i++) //统计这个矩形覆盖的面积
for(int j=y1;j<y2;j++)
if(!vis[i][j]){ //没有被覆盖过
sum++; //统计面积
vis[i][j]=1; //标注为已经覆盖
}
}
cout<<sum;
return 0;
}
3、标准解法
当n很大,n<100000,且坐标值很大时,暴力法显然会超时。
“矩形面积并”的标准解法是线段树的扫描线,建模和编码可不容易。参考博文“线段树”:
https://blog.csdn.net/weixin_43914593/article/details/108221534
其中的“7.1 矩形面积并”,和本题完全相同。