題意:求多個矩形面積的並
思路:掃描線算法,對每個矩形,用兩條平行於x軸的線段表示,然後對每條線段的y排序,然後就用平行於x軸的掃描線從y = 0出往上掃,每次求面積。這裏n只有100,所以可以用暴力解。
代碼如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<math.h>
#define N 1100
#define inf 0x7ffffff
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
double x[2*N];
struct node{
double x1,x2,h;
int flag;
bool operator < (const node &a)const
{
if(h != a.h) return h < a.h;
return flag < a.flag;
}
}s[N*2];
int color[2*N],b[N*2];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int n,cas = 1;
while(scanf("%d",&n) && n)
{
double x1,x2,y1,y2;
int i;
for(i = 0; i < n; i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
x[2*i] = x1;
x[2*i+1] = x2;
s[2*i].x1 = x1;
s[2*i].x2 = x2;
s[2*i].h = y1;
s[2*i].flag = 1;
s[2*i+1].x1 = x1;
s[2*i+1].x2 = x2;
s[2*i+1].h = y2;
s[2*i+1].flag = -1;
}
sort(s,s+2*n);
sort(x,x+2*n);
int tot = unique(x,x+2*n) - x;
memset(color,0,sizeof(color));
double ans = 0;
for(i = 0; i < 2*n-1; i++)
{
int l = lower_bound(x,x+tot,s[i].x1 ) - x;
int r = lower_bound(x,x+tot,s[i].x2 ) - x;
for(int j = 2*l; j <= 2*r; j++)//注意要擴大兩倍,不然有些數據過不了
color[j] += s[i].flag;
//for(int j = 0; j < tot; j++) cout<<color[j]<<" ";cout<<endl;
int k = 0;//我是用暴力解的,也可以用線段樹維護底邊長
if(color[0]) b[k++] = 0;
for(int j = 0; j < 2*tot; j++)
if(color[j] == 0 && color[j+1]) b[k++] = j+1;
else if(color[j] && color[j+1] == 0) b[k++] = j;
double temp = 0;
for(int j = 0; j < k; j+=2)
temp += ( x[ b[j+1]/2 ] - x[ b[j]/2 ]);
ans += temp* (s[i+1].h - s[i].h);
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2lf\n\n",ans);
}
return 0;
}