POJ 1151 & HDU 1542 Atlantis (矩形切割)

题目链接: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;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值