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\n"); 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\n",lo);
    }
    return 0;
}

 

posted @ 2016-04-16 17:23  vrsashly  阅读(177)  评论(0编辑  收藏  举报