1016.矩形合并
Total Submission(s): 242 Accepted Submission(s): 49
平面上有n个矩形,给定每个矩形的左下角坐标和右上角坐标。如果把重合的矩形合并成一个图形,则经过合并之后,还剩多少个图形?
第1行:一个整数n(1 <= n <= 100),表示矩形的数量。
第2至第n+1行:每行有4个整数,第i 行中的4个数字分别表示编号为i-1的矩形的左下角x、y坐标与右上角x、y坐标。
合并后剩余的图形数。
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;
}