zoukankan      html  css  js  c++  java
  • Dogs[HDU2822]

    Dogs

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2679 Accepted Submission(s): 1038


    Problem Description
    Prairie dog comes again! Someday one little prairie dog Tim wants to visit one of his friends on the farmland, but he is as lazy as his friend (who required Tim to come to his place instead of going to Tim's), So he turn to you for help to point out how could him dig as less as he could.

    We know the farmland is divided into a grid, and some of the lattices form houses, where many little dogs live in. If the lattices connect to each other in any case, they belong to the same house. Then the little Tim start from his home located at (x0, y0) aim at his friend's home ( x1, y1 ). During the journey, he must walk through a lot of lattices, when in a house he can just walk through without digging, but he must dig some distance to reach another house. The farmland will be as big as 1000 * 1000, and the up left corner is labeled as ( 1, 1 ).

    Input
    The input is divided into blocks. The first line in each block contains two integers: the length m of the farmland, the width n of the farmland (m, n ≤ 1000). The next lines contain m rows and each row have n letters, with 'X' stands for the lattices of house, and '.' stands for the empty land. The following two lines is the start and end places' coordinates, we guarantee that they are located at 'X'. There will be a blank line between every test case. The block where both two numbers in the first line are equal to zero denotes the end of the input.

    Output
    For each case you should just output a line which contains only one integer, which is the number of minimal lattices Tim must dig.

    Sample Input
    6 6
    ..X...
    XXX.X.
    ....X.
    X.....
    X.....
    X.X...
    3 5
    6 3

    0 0

    Sample Output
    3

    Hint

    Hint: Three lattices Tim should dig: ( 2, 4 ), ( 3, 1 ), ( 6, 2 ).

    题意:1000*1000的矩阵,'.'表示通过该格点耗时为1,'X'表示通过该格点耗时为0,求两个点之间最短的耗时。

    先直接SPFA来一遍,结果超时。再想想,发现可以优先扩展X格点,把SPFA的队列改成优先队列,通过,900ms。再想了一下,队列里的元素可以不用扩展完,碰到目标点就可以直接出解,400ms。看到网上其他人有提到用双向搜索,自己也写了一下,并没有成功,WA了,暂时没找到问题。并且,不幸的是,即使WA了,运行时间也已经达到了700ms。

    AC的代码:

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    char a[1005][1005];
    struct point {
        int x, y, w;
        friend bool operator <(const point &a, const point &b) {
            return a.w > b.w;
        }
    
    };
    const int dx[4] = { -1, 0, 1, 0};
    const int dy[4] = {0, 1, 0, -1};
    int d[1005][1005];
    bool vis[1005][1005];
    priority_queue<point> q;
    int main() {
        int n, m;
        while (scanf("%d%d", &m, &n) != EOF) {
            if (n == 0 && m == 0) {
                break;
            }
            for (int i = 0; i < m; i++) {
                scanf("%s", &a[i]);
            }
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            x1--;
            x2--;
            y1--;
            y2--;
            while (!q.empty()) {
                q.pop();
            }
            memset(d, 0x3F, sizeof(d));
            memset(vis, false, sizeof(vis));
            d[x1][y1] = 0;
            vis[x1][y1] = true;
            point p, v;
            int dis;
            p.x = x1;
            p.y = y1;
            p.w = 0;
            q.push(p);
            while (!q.empty()) {
                p = q.top();
                q.pop();
                vis[p.x][p.y] = false;
                for (int i = 0; i < 4; i++) {
                    v.x = p.x + dx[i];
                    v.y = p.y + dy[i];
                    if (v.x >= 0 && v.x < m && v.y >= 0 && v.y < n) {
                        dis = a[v.x][v.y] == '.' ? 1 : 0;
                        v.w = p.w + dis;
                        if (d[v.x][v.y] > d[p.x][p.y] + dis) {
                            d[v.x][v.y] = d[p.x][p.y] + dis;
                            if (!vis[v.x][v.y]) {
                                vis[v.x][v.y] = true;
                                q.push(v);
                            }
                        }
                    }
                }
                if (vis[x2][y2]) {
                    break;
                }
            }
            printf("%d
    ", d[x2][y2]);
        }
        return 0;
    }
    View Code

    失败的双向搜索:

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    char a[1005][1005];
    struct point {
        int x, y, w;
        friend bool operator <(const point &a, const point &b) {
            return a.w > b.w;
        }
    
    };
    const int dx[4] = { -1, 0, 1, 0};
    const int dy[4] = {0, 1, 0, -1};
    int d1[1005][1005], d2[1005][1005];
    int xA, xB, yA, yB, n, m;
    bool v1[1005][1005], v2[1005][1005];
    priority_queue<point> q1, q2;
    
    int bfs() {
        while (!q1.empty()) {
            q1.pop();
        }
        while (!q2.empty()) {
            q2.pop();
        }
        memset(d1, 0x3F, sizeof(d1));
        memset(v1, false, sizeof(v1));
        memset(d2, 0x3F, sizeof(d2));
        memset(v2, false, sizeof(v2));
        d1[xA][yA] = 0;
        d2[xB][yB] = 0;
        v1[xA][yA] = true;
        v2[xB][yB] = true;
        point p, v;
        int dis, w;
        p.x = xA;
        p.y = yA;
        p.w = 0;
        q1.push(p);
        p.x = xB;
        p.y = yB;
        p.w = 0;
        q2.push(p);
        bool find = false;
        int ret = 0x3FFFFFFF;
        for (int ii = 0;; ii++) {
            if (find) {
                return ret;
            }
            if (ii & 1) {
                w = q1.top().w;
                while (!q1.empty()) {
                    p = q1.top();
                    if (w != p.w) {
                        break;
                    }
                    q1.pop();
                    //v1[p.x][p.y] = false;
                    for (int i = 0; i < 4; i++) {
                        v.x = p.x + dx[i];
                        v.y = p.y + dy[i];
                        if (v.x >= 0 && v.x < m && v.y >= 0 && v.y < n) {
                            dis = a[v.x][v.y] == '.' ? 1 : 0;
                            if (d1[v.x][v.y] > d1[p.x][p.y] + dis) {
                                d1[v.x][v.y] = d1[p.x][p.y] + dis;
                                if (!v1[v.x][v.y]) {
                                    v1[v.x][v.y] = true;
                                    v.w = d1[v.x][v.y];
                                    q1.push(v);
                                }
                            }
                        }
                        if (v2[v.x][v.y]) {
                            //printf("%d %d %d %d
    ", v.x, v.y, d1[v.x][v.y], d2[v.x][v.y]);
                            //return d1[v.x][v.y] + d2[v.x][v.y] - dis;
                            find = true;
                            if (ret > d1[v.x][v.y] + d2[v.x][v.y] - dis) {
                                ret = d1[v.x][v.y] + d2[v.x][v.y] - dis;
                            }
                        }
                    }
                }
            } else {
                w = q2.top().w;
                while (!q2.empty()) {
                    p = q2.top();
                    if (w != p.w) {
                        break;
                    }
                    q2.pop();
                    //v2[p.x][p.y] = false;
                    for (int i = 0; i < 4; i++) {
                        v.x = p.x + dx[i];
                        v.y = p.y + dy[i];
                        if (v.x >= 0 && v.x < m && v.y >= 0 && v.y < n) {
                            dis = a[v.x][v.y] == '.' ? 1 : 0;
                            if (d2[v.x][v.y] > d2[p.x][p.y] + dis) {
                                d2[v.x][v.y] = d2[p.x][p.y] + dis;
                                if (!v2[v.x][v.y]) {
                                    v2[v.x][v.y] = true;
                                    v.w = d2[v.x][v.y];
                                    q2.push(v);
                                }
                            }
                        }
                        if (v1[v.x][v.y]) {
                            //printf("%d %d %d %d
    ", v.x, v.y, d1[v.x][v.y], d2[v.x][v.y]);
                            //return d1[v.x][v.y] + d2[v.x][v.y] - dis;
                            find = true;
                            if (ret > d1[v.x][v.y] + d2[v.x][v.y] - dis) {
                                ret = d1[v.x][v.y] + d2[v.x][v.y] - dis;
                            }
                        }
                    }
                }
            }
        }
        return 0;
    }
    int main() {
        while (scanf("%d%d", &m, &n) != EOF) {
            if (n == 0 && m == 0) {
                break;
            }
            for (int i = 0; i < m; i++) {
                scanf("%s", &a[i]);
            }
            scanf("%d%d%d%d", &xA, &yA, &xB, &yB);
            xA--;
            xB--;
            yA--;
            yB--;
            int ans = bfs();
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code

    顺便说,在#include<queue>之后,y1这个变量就不能定义了,因为重定义。写这个头文件的人太坑爹了。

  • 相关阅读:
    linux学习笔记 ftp命令
    linux 学习笔记 wc命令
    linux 学习笔记 finding people
    通配符
    linux 学习笔记 管道 pipe ls cp mv
    linux学习笔记 其他常用命令
    linux 学习笔记 执行脚本篇章
    solr分词一:mmseg4j
    solr介绍一:Analyzer(分析器)、Tokenizer(分词器)
    solr-4.10.2版本使用tomcat7部署
  • 原文地址:https://www.cnblogs.com/dramstadt/p/6269337.html
Copyright © 2011-2022 走看看