题目描述
现在我们在一个平面上画了n个矩形。每一个矩形的两边都与坐标轴相平行,且矩形定点的坐标均为整数。
现我们定义满足如下性质的图形为一个块:
1.每一个矩形都是一个块;
2.如果两个块有一段公共的部分,那么这两个块就会形成一个新的块,否则这两个块就是不同的。
示例:
图1中的矩形形成了两个不同的块。图2中的矩形形成了一个块。
任务:
请写一个程序:
1.从文本文件PRO.IN中读入各个矩形的顶点坐标;
2.找出这些矩形中不同的块的数目;
3.把结果输出到文本文件PRO.OUT中。
输入输出格式
输入格式:
文本文件PRO.IN的第一行包括一个整数n,1<=n<=7000,为矩形的数目。以下的n行为矩形顶点的坐标。
每一个矩形都是用四个整数来描述的:左下角的x坐标、左下角的y坐标、右上角的x坐标和右上角的y坐标。
所有的坐标都是不大于10000的非负整数。
输出格式:
在文本文件PRO.OUT中输出唯一的一个整数——这些矩形所形成的不同的块的数目。
输入输出样例
输出样例#1:
2
♦题目大意:
输入n个矩形,若两个矩形重合则将这两个矩形合并在一起,最后问一共有几块区域?
注意:两个矩形边与边重合能合成一块,而两个矩形点与点重合则不行!
♦思路:
显然,一个并查集不就搞定了吗?
可是!这道题的难点并不是并查集本身吧,更多的是怎么判断这两个矩形重合!
一开始,我的思路是将a矩形内的点全部标记一下,再枚举b矩形,看b矩形中有a矩形标记
过的几个点,若点大于1,则表示重合。虽然,这个方法是可行的,但是看数据范围,矩形
的坐标是不大于10000的非负整数,啊,显然就炸掉了!那怎么办呢?我我又很懒,那懒人
有懒方法,嗯,就从反向考虑吧!
如果b矩形的4个点的横坐标都大于a矩形的下点横坐标/都小于a矩形的上点横坐标..(依
旧很懒,如图,红色为a矩形,绿色为b矩形)
这4种情况则是不重合,那么怎么判断只有一个点重合的情况呢?其实只要特判一下就好了!
这样,这道题就AC了!
#include<bits/stdc++.h> using namespace std; int n; struct Squ{int x,y,xx,yy;}squ[7000+10]; int fa[7000+10]; int ans[7000+10],oo; int fi,fj; int c; int jud(int d,int dd) { int xf1=squ[d].x,yf1=squ[d].y,xf2=squ[d].xx,yf2=squ[d].yy; int xl1=squ[dd].x,yl1=squ[dd].y,xl2=squ[dd].xx,yl2=squ[dd].yy; if((xl1<xf1&&xl2<xf1)||(xl1>xf2&&xl2>xf2)||(yl1<yf1&&yl2<yf1)||(yl1>yf2&&yl2>yf2)) return 0; if((xl1==xf2&&yl1==yf2)||(xl1==xf2&&yl2==yf1)||(xl2==xf1&&yl1==yf2)||(xl2==xf1&&yl2==yf1)) return 0; return 1; } int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d%d",&squ[i].x,&squ[i].y,&squ[i].xx,&squ[i].yy); for(int i=1;i<=n;i++) fa[i]=i; for(int i=2;i<=n;i++) for(int j=1;j<=i-1;j++) { c=jud(j,i); if(c==1) { fi=find(i); fj=find(j); if(fi!=fj) fa[fi]=fj; } } for(int i=1;i<=n;i++) { fa[i]=find(i); ans[fa[i]]++; } for(int i=1;i<=n;i++) if(ans[i]>0) oo++; //for(int i=1;i<=n;i++) //printf("%d",fa[i]); printf("%d",oo); return 0; }