SDNU 1016.矩形合并 并查集


1016.矩形合并


Time Limit: 1000 MS    Memory Limit: 32768 KB

Total Submission(s): 242    Accepted Submission(s): 49


Description

平面上有n个矩形,给定每个矩形的左下角坐标和右上角坐标。如果把重合的矩形合并成一个图形,则经过合并之后,还剩多少个图形?


Input
第1行:一个整数n(1 <= n <= 100),表示矩形的数量。

第2至第n+1行:每行有4个整数,第i 行中的4个数字分别表示编号为i-1的矩形的左下角x、y坐标与右上角x、y坐标。


Output

合并后剩余的图形数。


Sample Input

3
0 0 2 2
1 1 4 4
4 4 5 5

Sample Output

2

Hint

相邻不重合的图形不合并


    首先考虑一下这个矩形什么情况下合并,因为相邻不重合的图形不合并,所以我直接判断是否不重合,如果不重合的话就一定是重合的。判断的方式就是,已知一个矩形A的左下角和右上角,然后用矩形B的左下角和矩形A的右上角进行比较,如果B的左下角在A右上角的上面或右边的话,一定不重合。以同样的方法再处理B的右下角,这样就能判断出来是否重合了。

    画个图来表示的话:


    如果下一个图形的左下角在红色区域就一定不重合,如果下一个图形的右下角再黑色区域就一定不重合,其余的全部判断为重合。
    然后是进行记录,输出重合后会剩余几个图形,表示一开始我是用一个数组来储存的,一开始全初始化为1,然后如果重合后面图形变为0,最后数有多少个1即可。不过这样的话
3
0 0 2 2
2 2 4 4
0 0 4 4
这一组数据过不了,然后旁边队友说用并查集来做。好吧,其实之前一直觉得并查集没必要记,之前几道并查集的题我都直接用自己思路做出来了......所以一直把他忽略掉了,结果这次= =改了并查集之后过了,好吧,原谅我之前把你无视掉了_(:зゝ∠)_
    下面AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool vis[105];
int pre[1005];

struct mar
{
     int lx,ly;
     int rx,ry;
};

mar m[105];

int goal(mar a,mar b)
{
     if(a.lx>=b.rx||a.ly>=b.ry)
          return 0;
     if(a.rx<=b.lx||a.ry<=b.ly)
          return 0;
     return 1;
}

int Find(int x)
{
     int r=x;
     while(r!=pre[r])
          r=pre[r];
     int i=x,j;
     while(pre[i]!=r)
     {
          j=pre[i];
          pre[i]=r;
          i=j;
     }
     return r;
}

int mix(int x,int y)
{
     int fx=Find(x),fy=Find(y);
     if(fx!=fy)
     {
          pre[fy]=fx;
     }
     return 0;
}

int main()
{
     int n;
     int i,j;
     int ans;
     while(scanf("%d",&n)!=EOF)
     {
          ans=0;
          memset(vis,0,sizeof(vis));
          memset(m,0,sizeof(m));
          for(i=1;i<=n;i++)
          {
               pre[i]=i;
               scanf("%d%d%d%d",&m[i].lx,&m[i].ly,&m[i].rx,&m[i].ry);
          }
          for(i=1;i<=n;i++)
          {
               for(j=i+1;j<=n;j++)
               {
                    if(goal(m[i],m[j])==1)
                         mix(i,j);
               }
          }
          for(i=1;i<=n;i++)
          {
               vis[Find(i)]=1;
          }
          for(i=1;i<=n;i++)
          {
               if(vis[i]==1)
                    ans++;
          }
          cout<<ans<<endl;
     }
     return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值