POJ 1151 Atlantis(重叠矩阵面积和=离散化)

558 篇文章 0 订阅
273 篇文章 0 订阅

POJ 1151 Atlantis(重叠矩阵面积和=离散化)

http://poj.org/problem?id=1151

题意: ZOJ 1128

       给你n个边平行于坐标轴的矩阵(任意两个矩阵可能重叠),让要你求这些矩阵的总面积.(注意x1<x2y1<y2)

分析:

       本题可以用线段树扫描线做,不过终归还是用离散化的思想来做,下面直接离散化做.(未使用线段树)

       假设输入的矩阵中共有num1个不同的x坐标和num2个不同的y坐标,那么整个二维平面就被分割成了(num1-1)*(num2-1)个小方格矩形.

       我们只要看上面(num1-1)*(num2-1)个小方格矩形哪些被某个大矩形覆盖,哪些没有被任何一个大矩形覆盖即可.

       我们令mp[i][j]=1表示以(x[i], y[j])点为左上角,以(x[i+1], y[j+1])点为右上角的那个小矩形被某个大矩形覆盖了.

       假设大矩形I的x坐标范围在[xi,xj]之间而y坐标在[yk,yh]之间.那么该大矩阵I肯定使得 所有的mp[a][b]==1. 其中i<=a<k且j<=b<h.

如上图两个绿色的矩阵正好使得了7个小矩阵被覆盖.那些小矩形对应的mp值都是1.

       最终我们只要把那些mp值==1的小矩形面积加起来即可.

AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200+5;
struct Node//矩形
{
    double x1,y1,x2,y2;
}nodes[maxn];
double x[maxn],y[maxn];
bool mp[maxn][maxn];

int find(double *x,double val,int n)//在数组x中找到val值的位置
{
    int L=0,R=n-1;
    while(R>=L)
    {
        int mid=L+(R-L)/2;
        if(x[mid]==val) return mid;
        else if(x[mid]>val) R=mid-1;
        else L=mid+1;
    }
    return -1;
}

int main()
{
    int n,num1,num2,kase=0;
    while(scanf("%d",&n)==1 && n)
    {
        num1=num2=0;//num1记录有多少个不同x值,num2记录y的
        memset(mp,0,sizeof(mp));
        for(int i=0;i<n;++i)
        {
            scanf("%lf%lf%lf%lf",&nodes[i].x1,&nodes[i].y1,&nodes[i].x2,&nodes[i].y2);
            x[num1++]=nodes[i].x1;
            x[num1++]=nodes[i].x2;
            y[num2++]=nodes[i].y1;
            y[num2++]=nodes[i].y2;
        }
        sort(x,x+num1);
        sort(y,y+num2);
        num1=unique(x,x+num1)-x;//去重
        num2=unique(y,y+num2)-y;//去重

        for(int i=0;i<n;++i)
        {
            //找出第i个原始大矩形覆盖的小矩形范围
            int L_x=find(x,nodes[i].x1,num1);
            int R_x=find(x,nodes[i].x2,num1);
            int L_y=find(y,nodes[i].y1,num2);
            int R_y=find(y,nodes[i].y2,num2);

            for(int j=L_x;j<R_x;++j)
            for(int k=L_y;k<R_y;++k)
                mp[j][k]=true;
        }
        double ans=0;
        for(int i=0;i<num1;++i)
        for(int j=0;j<num2;++j)if(mp[i][j])
            ans += (x[i+1]-x[i])*(y[j+1]-y[j]);
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",++kase,ans);
    }

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值