• 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
    
    
    
     
     
  • 相关阅读:
    vi编辑器
    数据发送的三种方式
    发送文件的三种方式
    提交表单提示框确定取消 点取消不会刷新页面
    input value="值栈的值"
    值栈
    struts2文件上传突破2M限制
    jsp取不到值栈的值
    站群--插件--点击量
    Java WebService 简单实例
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5337867.html
Copyright © 2020-2023  润新知