离散化 区域个数《挑战程序设计竞赛》164页

【问题描述】  

  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

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#define maxn 5005
using namespace std;
struct data
{
    int p,q;
}e[maxn*maxn];
int x1[maxn],x2[maxn],y1[maxn],y2[maxn],x[maxn],y[maxn];
int n,m,k,u=1,v=1,front,rear,ans=0; 
bool vis[maxn][maxn]; 
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
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 in()
{
    n=read();
    m=read();
    k=read();
    for(int i=1;i<=k;i++)
    {
        x1[i]=read();
        y1[i]=read();
        x2[i]=read();
        y2[i]=read();
    }
    int cnt1=0,cnt2=0;
    for(int i=1;i<=k;i++)           //将端点及其上下或左右的点存到x和y中 
    {
        x[++cnt1]=x1[i];
        if(x1[i]-1>0) x[++cnt1]=x1[i]-1;
        if(x1[i]+1<n) x[++cnt1]=x1[i]+1;
        x[++cnt1]=x2[i];
        if(x2[i]-1>0) x[++cnt1]=x2[i]-1;
        if(x2[i]+1<n) x[++cnt1]=x2[i]+1;

        y[++cnt2]=y1[i];
        if(y1[i]-1>0) y[++cnt2]=y1[i]-1;
        if(y1[i]+1<m) y[++cnt2]=y1[i]+1;
        y[++cnt2]=y2[i];
        if(y2[i]-1>0) y[++cnt2]=y2[i]-1;
        if(y2[i]+1<m) y[++cnt2]=y2[i]+1;
    }

    sort(x+1,x+cnt1+1);
    sort(y+1,y+cnt2+1);                 //本来是乱序,现在把需要的x和y有小到大排序

    for(int i=2;i<=cnt1;i++) if(x[i]!=x[i-1]) x[++u]=x[i];
    for(int i=2;i<=cnt2;i++) if(y[i]!=y[i-1]) y[++v]=y[i];      //去重 

    for(int i=1;i<=k;i++)
    {
        x1[i]=lower_bound(x+1,x+u+1,x1[i])-x;
        x2[i]=lower_bound(x+1,x+u+1,x2[i])-x;
        y1[i]=lower_bound(y+1,y+v+1,y1[i])-y;
        y2[i]=lower_bound(y+1,y+v+1,y2[i])-y;           //找离散化后线(障碍物)的坐标 
    }

    for(int i=1;i<=k;i++)                                   //生成地图 
    {
        for(int j=x1[i];j<=x2[i];j++)
        for(int t=y1[i];t<=y2[i];t++)
            vis[j][t]=1;
    }
}

void bfs(int x,int y)
{
    front=rear=1;
    e[rear++]=(data){x,y};
    vis[x][y]=1;

    while(front!=rear)
    {
        data i=e[front++];
        for(int k=0;k<4;k++)
        {
            int di=i.p+dx[k],dj=i.q+dy[k];
            if(vis[di][dj]) continue;
            if(di<1||dj<1||di>u||dj>v) continue;
            e[rear++]=(data){di,dj};
            vis[di][dj]=1;
        }
    }
}

void task()
{
    /*
    for(int i=1;i<=u;i++)
    {
        for(int j=1;j<=v;j++) printf("%d ",vis[i][j]);
        printf("\n");
    }
    */
    for(int i=1;i<=u;i++)
    for(int j=1;j<=v;j++) if(!vis[i][j])
    {
        ans++;
        bfs(i,j);
    }
    printf("%d",ans);
}

int main()
{
    //freopen("in1.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    in();
    task();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35546348/article/details/51981192
今日推荐