zoukankan      html  css  js  c++  java
  • India and China Origins---hdu5652(二分 + bfs)或者(并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5652

    题意:

    很久以前,中国和印度之间并没有喜马拉雅山相隔,两国的文化交流很频繁。随着喜马拉雅山海拔逐渐增加,两个地区的交流也越来越少,最终没有了来往。
    假设当时的地形和我画的一样,蓝色部分代表海洋,而且当时人们还没有发明轮船。黄色部分代表沙漠,而且沙漠上经常有野鬼散步,所以人们不敢到沙漠中行走。黑色的格子表示山峰,这些山峰都无比高大,所以人无法穿过。白色格子代表平原,
    人可以在平原上自由行走。人每次可以向相邻的四个格子走动。 此外,我们的考古学家发现还有一些山峰会逐渐形成,通过研究发现,位置在 (x, y)(x,y) (保证该位置之前没有山峰)的地方在 ii 年后出现了山峰。现在给你若干个位置出现山峰的时间,
    你可以计算出中国和印度之间的联系最早被彻底切断的时间吗?
    输入描述
    多组测试数据, 第一行为组数T(T10)。每组测试数据第一行包含两个数 N, M (1N,M500), 表示地图的大小。接下来 NN 行长度为 MM 的 0101 字符串。00代表白色格子,11 代表山峰。接下来有 Q(1QN×M) 行,
    i(1iQ) 两个整数 (x,y),0x<N,0y<M 表示在第 ii 年 (x,y) 出现了一座山峰。
    输出描述
    对于每组测试数据,输出一个数, 表示两国最早失联的时间。如果最终两国之间还有联系则输出 -1


    可以二分所有的时间,找到第一个让上下不连通的那个时间点;时间复杂度较高;

    #include <stdio.h>
    #include <algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    
    #define MOD 1000000007
    #define N 550
    typedef long long LL;
    
    
    char G[N][N];
    int m, n, x[N*N], y[N*N];
    
    int dir[4][2]= { {1, 0}, {-1,0}, {0, 1}, {0, -1} };
    
    
    struct node
    {
        int x, y;
    };
    
    int bfs(int x, int y, char Maps[][N])
    {
        node p, q;
        queue<node> Q;
        p.x = x, p.y = y;
        Q.push(p);
    
        int vis[N][N];
    
        memset(vis, 0, sizeof(vis));
        vis[x][y] = 1;
    
        while(Q.size())
        {
            p = Q.front();
            Q.pop();
    
            if(p.x == n-1)///可以连通;
                return 1;
    
            for(int i=0; i<4; i++)
            {
                q.x = p.x+dir[i][0];
                q.y = p.y+dir[i][1];
    
                if(q.x>=0 && q.x<n && q.y>=0 && q.y<m && Maps[q.x][q.y]=='0' && !vis[q.x][q.y])
                {
                    vis[q.x][q.y] = 1;
                    Q.push(q);
                }
            }
        }
        return 0;
    }
    
    int Judge(char Maps[][N])
    {
        for(int i=0; i<m; i++)
        {
            if(Maps[0][i]=='0')///枚举所有第一行可以走的点;
            {
                if( bfs(0, i, Maps) )///如果可以连通;
                    return 1;
            }
        }
        return 0;
    }
    
    void Init(char Map[][N], int Mid)
    {
        memset(Map, 0, sizeof(Map));
    
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                Map[i][j] = G[i][j];
    
        for(int i=1; i<=Mid; i++)
            Map[x[i]][y[i]] = '1';
    }
    
    int main()
    {
        int T, k;
    
        scanf("%d", &T);
    
        while(T--)
        {
            scanf("%d %d", &n, &m);
    
            for(int i=0; i<n; i++)
                scanf("%s", G[i]);
    
            scanf("%d", &k);
    
            for(int i=1; i<=k; i++)
                scanf("%d %d", &x[i], &y[i]);
    
            int L = 1, R = k, Mid = 0;
    
            char Map[N][N];
    
            while(L <= R)
            {
                Mid = (L+R) / 2;
    
                Init(Map, Mid);///重新构造地图,判断第Mid年加上是否连通;
    
                if( !Judge(Map) )///不连通;
                    R = Mid - 1;
                else
                    L = Mid + 1;
            }
            if(L > k) L = -1;
    
            printf("%d
    ", L);
        }
        return 0;
    }
    /*
    15
    3 4
    1100
    0001
    0000
    2
    0 3
    2 0
    */
    View Code

    重新做了下一这道题;发现是可以用并查集做的,时间复杂度相当于O(Q)的一共有n*m个点,
    我们可以编号为1-n*m我们把中国的区域地方看成编号0,印度的区域地方看成n*m+1;
    然后把所有的山峰放上去,把所有(i,j)位置能到达的点(xi, yi)建立到一个集合中去;
    倒着消除山峰,建立集合,当发现0和n*m+1在一个集中时,说明是当前山峰阻止了两国,答案就是当前山峰的年份;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define N 550
    #define PI 4*atan(1.0)
    #define mod 110119
    #define met(a, b) memset(a, b, sizeof(a))
    typedef long long LL;
    
    int f[N*N], n, m, x[N*N], y[N*N];
    char G[N][N];
    int dir[4][2] = {{-1,0},{1,0},{0,1},{0,-1}};
    
    int Find(int x)
    {
        if(x!=f[x])
            f[x] = Find(f[x]);
        return f[x];
    }
    
    void Union(int a, int b)
    {
        int pa = Find(a);
        int pb = Find(b);
        if(pa != pb)
            f[pa] = pb;
    }
    
    int Cul(int X, int Y)
    {
        if(Y<0 || Y>=m) return -1;
        if(X == -1) return 0;
        if(X == n) return n*m+1;
        if(G[X][Y] == '1') return -1;
        return X*m + Y + 1;
    }
    
    int main()
    {
        int T, q;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d %d", &n, &m);
    
            for(int i=0; i<n; i++)
                scanf("%s", G[i]);
    
            scanf("%d", &q);
            for(int i=1; i<=q; i++)
            {
                scanf("%d %d", &x[i], &y[i]);
                G[x[i]][y[i]] = '1';
            }
    
            for(int i=0; i<=n*m+5; i++)///初始化f;
                f[i] = i;
    
            for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(G[i][j] == '1') continue;
                int num1 = Cul(i, j);///找到当前点的编号;
                for(int k=0; k<4; k++)///与相邻的四点建立关系;
                {
                    int p = i + dir[k][0];
                    int q = j + dir[k][1];
                    int num2 = Cul(p, q);
                    if(num2 != -1)///-1代表不能联合;
                        Union(num1, num2);
                }
            }
            for(int i=q; i>0; i--)
            {
                G[x[i]][y[i]] = '0';///消除当前山峰;建立联合;
                int num1 = Cul(x[i], y[i]);
                for(int k=0; k<4; k++)
                {
                    int p = x[i] + dir[k][0];
                    int q = y[i] + dir[k][1];
                    int num2 = Cul(p, q);
                    if(num2 != -1)
                        Union(num1, num2);
                }
                if(Find(0) == Find(m*n+1))///当两点在一个集合中时;找到答案;
                {
                    printf("%d
    ", i);
                    break;
                }
            }
        }
        return 0;
    }
    View Code
    
    
    
     
     
  • 相关阅读:
    Android AHandle AMessage
    android java 与C 通过 JNI双向通信
    android 系统给应用的jar
    UE4 unreliable 同步问题
    UE4 difference between servertravel and openlevel(多人游戏的关卡切换)
    UE4 Run On owing Client解析(RPC测试)
    UE4 TSubclassOf VS Native Pointer
    UE4 内容示例网络同步Learn
    UE4 多人FPS VR游戏制作笔记
    UE4 分层材质 Layerd Materials
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5337867.html
Copyright © 2011-2022 走看看