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这个变量就不能定义了,因为重定义。写这个头文件的人太坑爹了。

原文地址:https://www.cnblogs.com/dramstadt/p/6269337.html