ccnu_2016_暑期模拟赛(2)---bfs

做完这题确实深有感触。
而且早上刚听完卿爷讲怎么对拍。刚好就在这个题用上了对拍的debug手段。也第一次体会到了对拍的便捷之处。
做这道题的过程还是很艰辛的:

—>昨天模拟赛赛时其实我已经明白这道题怎么写了,而且也将代码完成了90%左右。但是虽然写了,但是心里一直觉得自己过不了这题,可能是由于之前一直不会搜索导致的对我自己写的搜索算法没有信心,事实上,从我今天AC的代码来看,昨天的代码基本上是正确的。昨天赛时没有提交这题的代码。

—->今天过来补代码,先是过了样例,暂时又想不到什么测试数据,就提交了一发。果不其然。WA了。

—->WA了一发之后我就开始找bug,一开始一直在找bfs部分的错误,但是找了几遍一直找不到错误。

—->恰好早上卿爷讲了对拍的方法,我就顺便把这道题用对拍的方法找了找错误数据,一开始由于datamake.cpp没写好,生成的数据不够好,一直没找到错误数据,后来想了想,把随机数据的范围缩小了,这次终于找到了一组错误数据。一开始找到的时候还是很激动的,第一次用对拍的方法找到了错误数据。

—->通过这组错误数据,我发发现其实问题不在我的bfs部分,而在我预处理的部分。对于同一个点,如果有多个时间点有流星,应该取时间较小的。但是我取的是在数据输入中最早输入的时间。这个点错了问题。

—->把预处理部分改过来之后,再交一发。AC。
很高兴。第一次借助对拍解决了代码的bug,重要的是代码全是我自己写出来的。看着自己一步一步写出来的代码AC了。心里有种特别的快感。其实吧,可能由于我的性格原因。我及其反感查题解,所以我从头到尾没看一眼题解。可能从一定意义上来说,这是个好习惯,但是。遗憾的是,我既倔强地不看题解,又没有足够的智商快速地解决问题。所以后果就是我做题超级慢。甚至让我无法跟上大家的进度。去年集训也是,今年集训也是。这样看来,好像我又得不偿失。虽然已经这样想过很多次了。但是我还是很反感看题解。跟着别人给你铺好的路走。哎,可能我这样的性格就是这样吧。

总而言之。过这道题还是很开心的。虽然花的时间比较长。

【题面】
Description
Bessie hears that an extraordinary meteor shower is coming; reports say that these meteors will crash into earth and destroy anything they hit. Anxious for her safety, she vows to find her way to a safe location (one that is never destroyed by a meteor) . She is currently grazing at the origin in the coordinate plane and wants to move to a new, safer location while avoiding being destroyed by meteors along her way.

The reports say that M meteors (1 ≤ M ≤ 50,000) will strike, with meteor i will striking point (Xi, Yi) (0 ≤ Xi ≤ 300; 0 ≤ Yi ≤ 300) at time Ti (0 ≤ Ti ≤ 1,000). Each meteor destroys the point that it strikes and also the four rectilinearly adjacent lattice points.

Bessie leaves the origin at time 0 and can travel in the first quadrant and parallel to the axes at the rate of one distance unit per second to any of the (often 4) adjacent rectilinear points that are not yet destroyed by a meteor. She cannot be located on a point at any time greater than or equal to the time it is destroyed).

Determine the minimum time it takes Bessie to get to a safe place.

Input
* Line 1: A single integer: M
* Lines 2..M+1: Line i+1 contains three space-separated integers: Xi, Yi, and Ti

Output
* Line 1: The minimum time it takes Bessie to get to a safe place or -1 if it is impossible.

Sample Input
4
0 0 2
2 1 2
1 1 2
0 3 5
Sample Output
5

【题目大意】一个人在一个棋盘(额…这样理解助于后面做题23333)上看流星雨。每个棋盘的大小都是1*1.会有M个流星在某个时刻,掉落在棋盘上坐标为(x, y)的地方。砸坏点(x, y)以及该点上下左右,共5个点。砸坏的点就不能再走了。问这个人每次能向上下左右的任一个方向移动一步。问这个人最少花多少时间可以到达一个安全的地点。输出最少的时间,如果不能到达安全地点,输出-1。
【解法】有一个300*300的数组存这个棋盘。先将所有点置为-1,然后读取M个流星。将数组的值更新为该点第一次被破坏的时间。
如果起点就是安全的。直接输出0,否则从点(0,0)开始bfs.因为流星只会在落在300*300之内的位置。所以如果走到了这之外的合法位置,直接返回bfs的层数即可。
bfs判断下一个搜索点是否合法的时候需要额外判断当前点所在的bfs搜索层数以及该点最早被破坏的时间的大小。
一旦走到棋盘上为-1的点就是安全的,返回bfs层数。
【AC代码】

#include 
#include 
#include 
#include 
#include 
#include 

#define N 302

using namespace std;

struct Point{
    int x;
    int y;
    int depth;
};
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int ans;

int map[N][N];

bool in_board(int x, int y){                                               ///判断点在不在棋盘内
    if(x >= 0 && x <= 300 && y >= 0 && y <= 300){
        return true;
    }
    return false;
}

bool check(int x, int y, int depth){
    if(map[x][y] != -2 && map[x][y] > depth){
//        printf("合法判断如下:\n");
//        printf("map[%d][%d] = %d, depth = %d\n", x, y, map[x][y], depth);
        return true;
    }
    return false;
}

queueQ;
void bfs(Point start){
    map[start.x][start.y] = -2;
    Q.push(start);
//    printf("(%d, %d)入队, 第%d层\n", start.x, start.y, start.depth);
    while(!Q.empty()){
        Point temp;
        temp = Q.front();
//        printf("(%d, %d)出队, 第%d层\n", temp.x, temp.y, temp.depth);
        Q.pop();
        for(int i = 0; i < 4; i++){
            int ttx = temp.x + dx[i];
            int tty = temp.y + dy[i];
            if(in_board(ttx, tty)){
                if(map[ttx][tty] == -1){
                    ans = temp.depth + 1;
//                    printf("得出结果:\n");
//                    printf("map[%d][%d] = -1, depth = %d\n", ttx, tty, temp.depth);
                    return ;
                }
                if(check(ttx, tty, temp.depth + 1)){
                    Point newPoint;
                    newPoint.x = ttx;
                    newPoint.y = tty;
                    newPoint.depth = temp.depth + 1;
                    map[ttx][tty] = -2;
                    Q.push(newPoint);
//                    printf("(%d, %d)入队, 第%d层\n", ttx, tty, newPoint.depth);
                }
            }
            if(ttx > 300 || tty > 300){
                ans = temp.depth + 1;
                return ;
            }
        }
    }
}


int main(){
    int M;
    int x, y, t;
//    freopen("data.txt", "r", stdin);
//    freopen("myout.txt", "w", stdout);
    while(scanf("%d", &M) != EOF){
        memset(map, -1, sizeof(map));
        ans = -1;
        for(int i = 0; i < M; i++){                                         ///读取M个流星的落点
            scanf("%d%d%d", &x, &y, &t);
            if(map[x][y] == -1){
                map[x][y] = t;
                for(int i = 0; i < 4; i++){
                    int tx = x + dx[i];
                    int ty = y + dy[i];
                    if(in_board(tx, ty)){
                        if(map[tx][ty] == -1){
                            map[x + dx[i]][y + dy[i]] = t;
                        }
                        else{
                            map[x + dx[i]][y + dy[i]] = min(map[x + dx[i]][y + dy[i]], t);
                        }
                    }
                }
            }
            else{
                map[x][y] = min(map[x][y], t);
                for(int i = 0; i < 4; i++){
                    int tx = x + dx[i];
                    int ty = y + dy[i];
                    if(in_board(tx, ty)){
                        if(map[tx][ty] == -1){
                            map[x + dx[i]][y + dy[i]] = t;
                        }
                        else{
                            map[x + dx[i]][y + dy[i]] = min(map[x + dx[i]][y + dy[i]], t);
                        }
                    }
                }
            }
        }

//        for(int i = 0; i < 8; i++){
//            for(int j = 0; j < 8; j++){
//                printf("%4d ", map[i][j]);
//            }
//            printf("\n");
//        }

        if(map[0][0] == -1){                                                    ///起点是安全的
            printf("0\n");
        }
        else{
            Point start;
            start.x = 0;
            start.y = 0;
            start.depth = 0;
            bfs(start);
            printf("%d\n", ans);
//            if(ans == -1){                                                       ///无法到达安全的地点
//                printf("-1\n");
//            }
//            else{                                                               ///可以到达安全的地点
//                printf("%d\n", ans);                                            ///花费ans秒
//            }
        }
        while(!Q.empty()){
            Q.pop();
        }
    }
    return 0;
}
/*
   5   -1   -1    5   -1   -1   -1   -1
   5    1    5    5    5   -1    5   -1
   5    8    8    5   -1    5    5    1
  -1   -1    8   -1   -1   -1    5   -1
  -1   -1   -1   -1   -1    8   -1   -1
  -1   -1   -1   -1    8    8    8   -1
  -1    2   -1   -1   -1    8   -1    0
   2    2    2   -1   -1   -1    9    9
1


*/

你可能感兴趣的:(2016暑期集训)