《挑战程序设计竞赛》164页 区域个数
2016-07-22 11:18
323 查看
【问题描述】
w*h的格子画了n条或垂直或水平宽度为1的直线,求出这些格子被划分成了多少个4连块(上、下、左、右连通)。
【输入格式】
第一行包含两个整数:w和h,表示矩阵的列数和行数(行列编号都从1开始)。
第二行包含一个整数n,表示有n条直线。
接下来的n行,每行包含四个整数:x1,y1,x2,y2,表示一条直线的列号和行号。
【输出格式】
一个整数,表示区域数量。
【输入样例】
10 10
5
1 4 6 4
1 8 10 8
4 1 4 10
9 1 9 5
10 6 10 10
【输出样例】
6
【数据范围】
1<=w,h<=1000000 , 1<=n<=500
【来源】
《挑战程序设计竞赛》164页
这是一道离散化和连通分量的结合题(由于w,h范围太大,n的范围小,所以才想到用离散化,毕竟直接求连通分量要超时),首先我们需要讲点的坐标离散化,我采取的是x,y分开离散化(值得注意的是除了直线的坐标以外,它周围的坐标也要离散化),然后再在离散化了的图上进行连通分量的查找。
w*h的格子画了n条或垂直或水平宽度为1的直线,求出这些格子被划分成了多少个4连块(上、下、左、右连通)。
【输入格式】
第一行包含两个整数:w和h,表示矩阵的列数和行数(行列编号都从1开始)。
第二行包含一个整数n,表示有n条直线。
接下来的n行,每行包含四个整数:x1,y1,x2,y2,表示一条直线的列号和行号。
【输出格式】
一个整数,表示区域数量。
【输入样例】
10 10
5
1 4 6 4
1 8 10 8
4 1 4 10
9 1 9 5
10 6 10 10
【输出样例】
6
【数据范围】
1<=w,h<=1000000 , 1<=n<=500
【来源】
《挑战程序设计竞赛》164页
这是一道离散化和连通分量的结合题(由于w,h范围太大,n的范围小,所以才想到用离散化,毕竟直接求连通分量要超时),首先我们需要讲点的坐标离散化,我采取的是x,y分开离散化(值得注意的是除了直线的坐标以外,它周围的坐标也要离散化),然后再在离散化了的图上进行连通分量的查找。
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=505; int x1[maxn],x2[maxn],y1[maxn],y2[maxn]; int x[maxn*6],y[maxn*6]; int n,w,h,nx,ny; int dx[]={0,0,-1,1}; int dy[]={1,-1,0,0}; bool vis[maxn*6][maxn*6]; struct shu { int mx,my; }q[maxn*maxn*36]; int read() { int x=0,ok=0; char ch; ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); while((ch>='0'&&ch<='9')||ch=='-') { if(ch=='-') ok=1; else x=x*10+ch-'0'; ch=getchar(); } return ok==1?-x:x; } void init() { w=read(); h=read(); n=read(); for(int i=1;i<=n;i++) { x1[i]=read(); y1[i]=read(); x2[i]=read(); y2[i]=read(); } } void work() { int k=0,t=0; for(int i=1;i<=n;i++) { x[++k]=x1[i]; if(x1[i]-1>0) x[++k]=x1[i]-1; if(x1[i]+1<w) x[++k]=x1[i]+1; x[++k]=x2[i]; if(x2[i]-1>0) x[++k]=x2[i]-1; if(x2[i]+1<w) x[++k]=x2[i]+1; y[++t]=y1[i]; if(y1[i]-1>0) y[++t]=y1[i]-1; if(y1[i]+1<h) y[++t]=y1[i]+1; y[++t]=y2[i]; if(y2[i]-1>0) y[++t]=y2[i]-1; if(y2[i]+1<h) y[++t]=y2[i]+1; } sort(x+1,x+1+k); sort(y+1,y+1+t); nx=1; for(int i=2;i<=k;i++) if(x[i]!=x[i-1]) x[++nx]=x[i]; ny=1; for(int i=2;i<=t;i++) if(y[i]!=y[i-1]) y[++ny]=y[i]; for(int i=1;i<=n;i++) { x1[i]=lower_bound(x+1,x+1+nx,x1[i])-x; x2[i]=lower_bound(x+1,x+1+nx,x2[i])-x; y1[i]=lower_bound(y+1,y+1+ny,y1[i])-y; y2[i]=lower_bound(y+1,y+1+ny,y2[i])-y; } for(int i=1;i<=n;i++) { for(int j=x1[i];j<=x2[i];j++) for(int k=y1[i];k<=y2[i];k++) vis[j][k]=1; } } void bfs(int x,int y) { int root=0,frond=0; q[root++]=(shu){x,y}; vis[x][y]=1; while(root!=frond) { shu i=q[frond++]; for(int k=0;k<4;k++) { int xx=i.mx+dx[k],yy=i.my+dy[k]; if(xx<1||xx>nx||yy<1||yy>ny) continue; if(vis[xx][yy]) continue; q[root++]=(shu){xx,yy};; vis[xx][yy]=1; } } } int main() { //freopen("in.txt","r",stdin); init(); work(); int ans=0; for(int i=1;i<=nx;i++) for(int j=1;j<=ny;j++) if(vis[i][j]==0) { bfs(i,j); ans++; } printf("%d",ans); return 0; }
相关文章推荐
- JUnit教程-- 创建套件测试
- 求LPS——最长回文子序列
- leetcode150 Evaluate Reverse Polish Notation
- Linux上面用QCreator搭载opencv工程的创建
- Trimmomatic对raw reads的去接头 赫尔过滤
- leetcode150 Evaluate Reverse Polish Notation
- iOS 项目经验总结
- 改善既有代码的设计(一)----------小案例展示重构的意义
- PAT-B 1046. 划拳
- JMeter-负载测试
- truncate table drop
- Freemarker判断序列中是否包含某个元素
- 更改jdk的路径
- 习题12 提示别人
- 移动前端手机输入法自带emoji表情字符处理
- 使用Wireshark 抓取数据包
- hdu 5734 Acperience(2016多校第二场)
- 自定义系统导航栏UINavigationBarController。
- JavaScript中textRange对象使用方法总结(IE only!)
- Android-transulcent-status-bar总结