本文链接: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#include #include #include #include #include #include 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;}