题目链接:http://poj.org/problem?id=1151
这个题目数据量不大,可以直接用矩形切割来做
不过这个题目有点坑,给的不是左上角和又下角,给的是左下角和右上角的,害我样例通不过
然后就是矩形切割,开始没理解,老是想不通,后来明白后发现这个思想还是挺经典的
矩形分割就是用现在要插入的矩形来分割现在集合中已经有的矩形,那么分割的时候不是我们想当然的分割
的,他是这样,保证当前插入的这块保留,把所有矩形与这块相交的部分去掉,然后剩下的部分可能不规则
把剩下的部分分割成矩形,依次加入集合,最后把切割的这个也加入(因为集合中已经没有和本身重合的了)
代码很简洁
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define maxn 100000
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) ((a)<(b)?(a):(b))
struct rect{
double x1,y1,x2,y2;
bool flag;
rect(double a=0,double b=0,double c=0,double d=0,bool f=true):x1(a),y1(b),x2(c),y2(d),flag(f){}
}po[maxn],rec;
int n,pos;
double ans;
bool is_cross(const rect &a,const rect &b){
if(a.y1 >= b.y2 || a.x1 >= b.x2 || a.y2 <= b.y1 || a.x2 <= b.x1)
return false;
return true;
}
int cut_rect(rect &a,rect &b){//a cut b
double k1,k2,k3,k4;
k1=MAX(a.x1,b.x1),k2=MIN(a.x2,b.x2);
if(b.x1 < k1)
po[pos++]=rect(b.x1,b.y1,k1,b.y2);
if(b.x2 > k2)
po[pos++]=rect(k2,b.y1,b.x2,b.y2);
k3=MAX(a.y1,b.y1),k4=MIN(a.y2,b.y2);
if(b.y1 < k3)
po[pos++]=rect(k1,b.y1,k2,k3);
if(b.y2 > k4)
po[pos++]=rect(k1,k4,k2,b.y2);
return 0;
}
int main(){
int i,j,r,k=0;
while(scanf("%d",&n),n){
rec.flag=true,po[0].flag=true;
pos=1;
scanf("%lf%lf%lf%lf",&po[0].x1,&po[0].y1,&po[0].x2,&po[0].y2);
for(i=1;i<n;i++){
scanf("%lf%lf%lf%lf",&rec.x1,&rec.y1,&rec.x2,&rec.y2);
r=pos;
for(j=0;j<r;j++){
if(po[j].flag==false || !is_cross(rec,po[j])){
continue;
}
po[j].flag=false;
cut_rect(rec,po[j]);
}
po[pos++]=rec;
}
ans=0;
for(i=0;i<pos;i++)
if(po[i].flag)
ans+=(po[i].x2-po[i].x1)*(po[i].y2-po[i].y1);
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++k,ans);
}
return 0;
}