zoukankan      html  css  js  c++  java
  • HDU 5652 India and China Origins(二分 + DFS)

    本文链接:http://www.cnblogs.com/Ash-ly/p/5398851.html

    题意:

      中国和印度之间有一片地方,把这片地方抽象化,于是就可以看成一个N * M矩阵,其中黑色的代表高山不能走过去,白色的代表平原,可以通行,人每次可以选择往上下左右四个方向移动,但是随着时间的变化某些白色的平原会变成黑色的高山,从而变为不可通行,题目中给出一个代表地势的图,然后有 Q 次操作,第 i 次操作 代表在第 i 年 (x, y)处的平原变成了高山,即白色变为了黑色。问中国印度最早彻底断绝的时间,如果在 Q 年后还没有断绝就输出 -1;

    思路:

      对于0 - Q年份进行二分,然后利用DFS枚举起点判断连通性。如果在mid年时隔绝已经形成,那么说明答案在[lo-mid]之间,继续二分,否则说明答案在(mid,hi]之间。回溯时不用恢复原图,因为每个点只需要判断一次连通性就可以了。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    
    int beginX, beginY;
    int stepX[] = {0, 0, -1, 1};//每次可选的方向
    int stepY[] = {-1, 1, 0, 0};
    int date[503][503];
    int Gra[503][503];
    int flag ;
    int N, M;
    
    int check(int x, int y){//能否走到x , y点
        if(Gra[x][y] == -2 || Gra[x][y] == 1 || Gra[x][y] == -1)
            return 0;
        return 1;
    }
    
    void backtrack(int x, int y){
        if( x == N )//走到了最底下,图连通
            flag = 1;
        else{
            for(int i = 0; i <= 3; i++){
                int tx = x + stepX[i];
                int ty = y + stepY[i];
                if(check(tx, ty)){
                    Gra[tx][ty] = -2;//已经走过
                    if(flag) return;
                    backtrack(tx, ty);//回溯继续求解
                }
            }
        }
    }
    
    struct Point{
        int x;
        int y;
    }point[250007];
    
    
    int isOk(int mid){
        memcpy(Gra, date, sizeof(date));
        for(int j = 1; j <= mid; j++)
            Gra[ point[j].x ][ point[j].y ] = 1;
        for(int i = 1; i <= M; i++){
            if(Gra[1][i] != 1){
                beginY = i;
                beginX = 1;
                flag = 0;
                backtrack(1, i);
                if(flag == 1) return 0;
            }
        }
        return 1;
    }
    
    int main(){
       // freopen("in.txt","r", stdin);
        int T;
        scanf("%d",&T);
        while(T--){
            memset(date, -1,  sizeof(date));
            scanf("%d%d",&N, &M);
            for(int i = 1; i <= N; i++)
                for(int j = 1; j <= M; j++)
                    scanf("%1d",&date[i][j]);
            int Q;
            scanf("%d",&Q);
            for(int i = 1; i <= Q; i++){
                int a,b;
                scanf("%d%d",&a, &b);
                point[i].x = a + 1;
                point[i].y = b + 1;
            }
            if(isOk(Q) == 0) {printf("-1
    "); continue;}
            int lo = 0;
            int hi = Q;
            int ans = -1;
            while(lo <= hi){//二分求解YES_LEFT
                int mid = lo + (hi - lo) / 2;
                if( isOk(mid) ) hi = mid - 1;
                else lo = mid + 1;
            }
            printf("%d
    ",lo);
        }
        return 0;
    }
  • 相关阅读:
    c++ ShellExecuteEx调用java打包的exe程序
    麻省理工学院公开课-第四讲:快速排序 及 随机化 算法
    Win10的IIS与以前版本的一个区别
    干就行了!!!写程序就像珊瑚,分支太多,哪有那么多复用!
    NPoco的使用方法
    为什么前端要写标准代码?
    对于委托、事件、观察者模式最一目了然的代码段
    delphi处理消息的几种方式
    哎呀妈呀,吓死我了,幸好服务器没崩溃。
    Delphi的Hint介绍以及用其重写气泡提示以达到好看的效果
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5398851.html
Copyright © 2011-2022 走看看