zoukankan      html  css  js  c++  java
  • 矩阵的并

    Description

    在 X-Y 坐标平面上,给定多个矩形,它们的边分别与坐标轴平行。请计算它们的并的面积。 

    输入格式

    输入第一行为一个整数 n,1<=n<=100,表示矩形的数量。
    接下来有 n 行,每行包括四个数:x1,y1,x2,y2 (0<=x1<x2<=100000;0<=y1<y2<=100000),
    用空格分开,不一定为整数。
    (x1,y1)表示一个长方形的左下顶点坐标,(x2,y2)表示右上顶点坐标。 
    

    输出格式

    n个矩形的并的面积,保留两位小数
    
    
    输入样例
    2
    0 0 2 2 
    1 1 3 3 
    
    
    输出样例
    7.00
    
    
    

    思路1:


    原来的思路是有一些错误的,即我把每两个矩形的并面积算作 S = 两个矩形面积相加 - 两个矩形相交的面积,这思路乍一看没错,我提交时也这么想,但是WA了。问题就出在了如果三个矩形都有并的面积时
    三个矩形相交的面积会被多减了一次导致错误,那么四个矩形相交、五个呢,这个bug有点难改,如果有神犇有思路还望指导一下,以下是我第一次的代码(WA的)
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e5+10;
    
    struct Rec{
        double x1,y1;
        double x2,y2;
    };
    
    Rec rec[maxn];
    
    int main(){
        int m;
        double sums = 0,subs = 0; 
        scanf("%d",&m);
        for(int i=0 ;i<m ;i++){
            scanf("%lf%lf%lf%lf",&rec[i].x1, &rec[i].y1, &rec[i].x2,&rec[i].y2);
            sums+= (rec[i].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
        }
    
        for(int i=0 ;i<m ;i++){ //去掉包含的
            for(int j=0 ;j<m ;j++){
                if(i == j)  continue;
                else if(rec[i].x1 >= rec[j].x1 && rec[i].x2 <= rec[j].x2)
                    if(rec[i].y1 >= rec[j].y1 && rec[i].y2 <= rec[j].y2){
                        sums -= (rec[i].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
                        rec[i].x1 = rec[i].x2 =rec[i].y1 =rec[i].y2 = 0;
                    }
            }
        }
        //double old = 0, subss;
        for(int i=0 ;i<m ;i++){  //以i为后面的和里面的矩形(被包围)
                //subss = subs;
            for(int j=0 ;j<m ;j++){
               // old = subs;
                if(i == j) continue;
                if(rec[i].x1 > rec[j].x1 && rec[i].x2 > rec[j].x2 && rec[j].x2 > rec[i].x1){ //相交
                    if(rec[i].y2 > rec[j].y2 && rec[i].y1 > rec[j].y1 && rec[i].y1 < rec[j].y2) //右上
                        subs += (rec[j].x2- rec[i].x1)*(rec[j].y2 - rec[i].y1);
                    else if(rec[i].y2 < rec[j].y2 &&rec[i].y1 > rec[j].y1) //右中
                        subs += (rec[j].x2 - rec[i].x1)*(rec[i].y2 - rec[i].y1);
                    else if(rec[i].y2 < rec[j].y2 && rec[i].y2 > rec[j].y1 &&rec[i].y1 < rec[j].y1) //右下
                        subs += (rec[j].x2 - rec[i].x1)*(rec[i].y2 - rec[j].y1);
                    else if(rec[i].y1 < rec[j].y1 && rec[i].y2 > rec[j].y2)
                        subs +=(rec[j].x2 - rec[i].x1)*(rec[j].y2 - rec[j].y1); //右包含
                }
                else if(rec[j].x1 <= rec[i].x1 && rec[i].x2 <= rec[j].x2){ //中包含
                    int lenx = (rec[i].x2 - rec[i].x1);
                    if(rec[i].y1 > rec[j].y1 && rec[i].y2 > rec[j].y2 && rec[i].y1 <rec[j].y2) //中上
                        subs += lenx*(rec[j].y2 - rec[i].y1);
                    else if(rec[i].y1 < rec[j].y1 && rec[i].y2 < rec[j].y2 && rec[i].y2 > rec[j].y1) //下包含
                        subs +=(rec[i].y2 - rec[j].y1)*lenx;
                    else if(rec[i].y1 < rec[j].y1 && rec[i].y2 > rec[j].y2) //贯穿
                        subs += (rec[j].y2 - rec[j].y1)*lenx;
                }
                //printf("%d %d %.2lf 
    ",i,j,subs - old);
            }
            //printf("*********%.2lf
    ",subs - subss);
        }
        printf("%.2lf
    ",sums - subs);
    }
     

    思路2:

    后面这个思路是我看了大佬的代码才想出来的,主要思路是枚举在合并后矩形的各个横、纵坐标,再把横纵坐标组成的矩形面积相加,及矩阵的并面积(这里我觉得我说的不太清楚,具体看代码吧)
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    struct rectangle{    //结构体,保存矩形
           float x1;
           float y1;
           float x2;
           float y2; 
    };
           
    rectangle arr[101];    
    float x[200];
    float y[200];
    int flag[200][200]; 
           
    int main(){
       
       float count=0;
       int n;
       int k=0;
       scanf("%d",&n);                             //数据输入
        for(int i=0;i<n;i++){         
                scanf("%f",&arr[i].x1);
                scanf("%f",&arr[i].y1);
                scanf("%f",&arr[i].x2);
                scanf("%f",&arr[i].y2);
                x[k]=arr[i].x1;                   //保存所有X坐标到X[]数组,Y 到Y[]数组
                y[k]=arr[i].y1;
                k++;
                x[k]=arr[i].x2;
                y[k]=arr[i].y2;
                k++;
                }
        sort(x,x+k);        //分别排序     
        sort(y,y+k);for(int h=0;h<n;h++)          //循环查找在矩形内的小矩形
           for(int i=0;i<2*n;i++){
              if(x[i]>=arr[h].x2)
                  break;     
              for(int j=0;j<2*n;j++){
                 if(y[j]>=arr[h].y2)
                    break;
                 if(x[i]>=arr[h].x1&&y[j]>=arr[h].y1)
                    flag[i][j]=1;                       //符合,标志
              }
           }
                                       
          
        for(int i=0;i<2*n;i++)               //统计面积
           for(int j=0;j<2*n;j++)
              count+=flag[i][j]*(x[i+1]-x[i])*(y[j+1]-y[j]);     
                 
        printf("%.2f",count);
       return 0;
    }
    
    
    
     
  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/wxx23-IOU/p/13944615.html
Copyright © 2011-2022 走看看