C - Count the Regions Gym - 102014C 思维+搜索

本文探讨了使用离散化和二进制优化技术解决二维平面上多个矩形将平面分割成多少部分的问题。介绍了两种实现方法,一种是通过离散化坐标和搜索算法,另一种是利用二进制表示被矩形覆盖的区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://vj.e949.cn/b743540e901f680c3f865e202a43ca28?v=1543480981

题意:

         给你二维坐标系上的n(n<=50)个矩形,问这些矩形把二维平面分成了几部分。

 

做法:

       队友的做法好神奇。队友把点离散化,然后每个点的坐标乘2,把划线的地方打上标记,这样可以使没有被覆盖到的空位留出至少一个点的空位,然后用搜索把点覆盖。

       我敲的做法是用二进制优化,因为最多有50个矩形,所以被一个矩形覆盖的地方我用一位二进制表示,然后通过搜索去找与这个数字相似的(即被同样覆盖的地方),再打标记。


代码1:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9;
map<ll,ll> mpx,mpy;
map<ll,ll>::iterator it;
ll mp[255][255];
ll xl[55],xr[55],yl[55],yh[55],vis[255][255],numx,numy;
void dfs(int x,int y,ll a){
    if(x<0||x>numx||y<0||y>numy||vis[x][y]||mp[x][y]!=a) return ;
    vis[x][y]=1;
    dfs(x+1,y,a);
    dfs(x-1,y,a);
    dfs(x,y+1,a);
    dfs(x,y-1,a);
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        if(n==0) break;
        memset(vis,0,sizeof(vis));
        memset(mp,0,sizeof(mp));
        mpx.clear(); mpy.clear();
        mpx[-inf]=1,mpx[inf]=1,mpy[-inf]=1,mpy[inf]=1;
        for(int i=1;i<=n;i++){
            scanf("%lld%lld%lld%lld",&xl[i],&yh[i],&xr[i],&yl[i]);
            mpx[xl[i]]=1,mpx[xr[i]]=1,mpy[yl[i]]=1,mpy[yh[i]]=1;
        }
        numx=0,numy=0;
        for(it=mpx.begin();it!=mpx.end();it++)
            it->second=++numx;
        for(it=mpy.begin();it!=mpy.end();it++){
            it->second=++numy;
            //cout<<it->first<<" "<<it->second<<endl;
        }
        for(int i=1;i<=n;i++){
            for(int j=mpx[xl[i]];j<=mpx[xr[i]]-1;j++){
                for(int k=mpy[yl[i]];k<=mpy[yh[i]]-1;k++){
                    mp[j][k]|=(1ll<<(i-1));
                }
            }
        }

        int ans=0;
        for(int i=1;i<=numx;i++){
            for(int j=1;j<=numy;j++){
                if(!vis[i][j]){
                    ans++;
                    dfs(i,j,mp[i][j]);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

代码2。

#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
int Map[405][405],vis[405][405];
struct node
{
    int x1,y1,x2,y2;
}p[155];
int x[405],y[405];
int n;
queue<pa>Q;
int xmov[]={1,0,-1,0};
int ymov[]={0,1,0,-1};
void bfs(int sx,int sy)
{
    Q.push({sx,sy});
    vis[sx][sy]=1;
    while(!Q.empty())
    {
        int x=Q.front().first,y=Q.front().second,nx,ny;
        Q.pop();
        for(int i=0;i<4;i++)
        {
            nx=x+2*xmov[i],ny=y+2*ymov[i];
            if(nx>201||nx<1||ny>201||ny<1||Map[nx-xmov[i]][ny-ymov[i]]==1||vis[nx][ny]==1)
                continue;
            vis[nx][ny]=1;
            Q.push({nx,ny});
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)
            break;
        int x1,x2,y1,y2;
        memset(vis,0,sizeof(vis));
        memset(Map,0,sizeof(Map));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
            x[i*2-1]=p[i].x1,x[i*2]=p[i].x2;
            y[i*2-1]=p[i].y1,y[i*2]=p[i].y2;
        }
        sort(x+1,x+1+2*n),sort(y+1,y+1+2*n);
        int allx=unique(x+1,x+1+2*n)-x-1;
        int ally=unique(y+1,y+1+2*n)-y-1;
        for(int i=1;i<=n;i++)
        {
            p[i].x1=(lower_bound(x+1,x+1+allx,p[i].x1)-x)*2;
            p[i].x2=(lower_bound(x+1,x+1+allx,p[i].x2)-x)*2;
            p[i].y1=(lower_bound(y+1,y+1+ally,p[i].y1)-y)*2;
            p[i].y2=(lower_bound(y+1,y+1+ally,p[i].y2)-y)*2;
            //cout<<p[i].x1<<" "<<p[i].y2<<endl;
            for(int j=p[i].x1;j<=p[i].x2;j++)
                Map[j][p[i].y1]=Map[j][p[i].y2]=1;
            for(int j=p[i].y2;j<=p[i].y1;j++)
                Map[p[i].x1][j]=Map[p[i].x2][j]=1;
        }
        int ans=0;
        for(int i=1;i<=201;i+=2)
        {
            for(int j=1;j<=201;j+=2)
            {
                if(!vis[i][j])
                {
                    bfs(i,j);
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值