zoukankan      html  css  js  c++  java
  • HDU 5652 India and China Origins(二分+并查集||BFS)

    http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=682&pid=1003

    中文题意,不再描述。

    题解:

      顺序给山峰出现的时间,明显地用二分来查找。然后连通块用并查集(也可以BFS,复杂度都是O(n))来维护。

    1.并查集

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=505;
    char maze[maxn][maxn];
    bool vis[maxn][maxn];
    int n,m,q,par[maxn*maxn];
    int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
    struct node
    {
        int x,y;
    }p[maxn*maxn];
    int find(int x)
    {
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        x=find(x);
        y=find(y);
        if(x==y)
            return ;
        par[x]=y;
    }
    bool check(int t)
    {
        for(int i=0;i<=n*m+1;i++)
            par[i]=i;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(maze[i][j]=='1')
                    vis[i][j]=true;
                else
                    vis[i][j]=false;
        for(int i=1;i<=t;i++)
            vis[p[i].x][p[i].y]=true;
        for(int i=1;i<=n;i++)//最上方编号为0,1-n行编号为1-n*m,最后一行(n+1)编号为n*m+1
            for(int j=1;j<=m;j++)
            {
                if(vis[i][j])
                    continue;
                for(int k=0;k<4;k++)
                {
                    int nx=i+dx[k],ny=j+dy[k];
                    if(ny<1||ny>m)
                        continue;
                    if(nx==0)
                        unite((i-1)*m+j,0);
                    else if(nx==n+1)
                        unite((i-1)*m+j,n*m+1);
                    else if(!vis[nx][ny])
                            unite((i-1)*m+j,(nx-1)*m+ny);
                }
            }
        if(find(0)==find(n*m+1))
            return true;
        return false;
    }
    void solve()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",maze[i]+1);
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].x++,p[i].y++;
        }
        if(check(q))//不存在解
        {
            cout<<"-1"<<endl;
            return ;
        }
        int l=1,r=q,ans=0;
        while(l<=r)//二分
        {
            int mid=(l+r)/2;
            if(!check(mid))
            {
                r=mid-1;
                ans=mid;
            }
            else
                l=mid+1;
        }
        cout<<ans<<endl;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            memset(vis,false,sizeof(vis));
            solve();
        }
        return 0;
    }

     2.BFS

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int maxn=505;
    char maze[maxn][maxn];
    bool vis[maxn][maxn];
    int n,m,q;
    int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
    struct node
    {
        int x,y;
    }p[maxn*maxn];
    bool bfs()
    {
        queue<node> que;
        node cur;
        for(int i=1;i<=n;i++)
        {
            cur.x=0;
            cur.y=i;
            que.push(cur);
        }
        while(que.size())
        {
            cur=que.front();
            que.pop();
            if(cur.x==n+1)
                return true;
            for(int i=0;i<4;i++)
            {
                node next=cur;
                next.x+=dx[i],next.y+=dy[i];
                if(0<=next.x&&next.x<=n+1&&1<=next.y&&next.y<=m&&!vis[next.x][next.y])
                {
                    vis[next.x][next.y]=true;
                    que.push(next);
                }
            }
        }
        return false;
    }
    bool check(int t)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(maze[i][j]=='1')
                    vis[i][j]=true;
                else
                    vis[i][j]=false;
        for(int i=1;i<=t;i++)
            vis[p[i].x][p[i].y]=true;
        return bfs();
    }
    
    void solve()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",maze[i]+1);
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].x++,p[i].y++;
        }
        if(check(q))
        {
            cout<<"-1"<<endl;
            return ;
        }
        int l=1,r=q,ans=0;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(!check(mid))
            {
                r=mid-1;
                ans=mid;
            }
            else
                l=mid+1;
        }
        cout<<ans<<endl;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            memset(vis,false,sizeof(vis));
            solve();
        }
        return 0;
    }

      

  • 相关阅读:
    设计模式学习总结状态模式(State Method)
    设计模式学习总结命令模式(Cmmand Pattern)
    Linux常用命令
    设计模式学习总结代理模式(Proxy Method)
    设计模式学习总结模板方法模式(Template Method)
    设计模式学习总结桥接模式(Bridge Pattern)
    设计模式学习总结适配器模式(Adapter Pattern)
    设计模式学习总结迭代器模式(Iterator Pattern)
    设计模式学习总结责任链模式(Chain of Responsibility Method)
    spingboot @Transactional 不回滚
  • 原文地址:https://www.cnblogs.com/orion7/p/7344485.html
Copyright © 2011-2022 走看看