您的位置:首页 > 其它

《挑战程序设计竞赛》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分开离散化(值得注意的是除了直线的坐标以外,它周围的坐标也要离散化),然后再在离散化了的图上进行连通分量的查找。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: