题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4198

题目大意: 给你一张地图,”S“为起点,"#"不能走,走过一个"."需要1个单位时间, 走过一个”@“需要d+1的单位时间,求中起点走出地图的最短时间……

思路:我的第一反应是拆点……把一个“@”拆成d+1个,然后BFS但是这么写真的好麻烦啊!

可以用优先队列+BFS,先扩展路径长度比较短的点,然后不就求出最短路了么?

表示我写BFS都是手工队列……果然得好好学STL……

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int N = 1010;
struct ty
{
    int x, y, time;
    friend bool operator < (ty a, ty b)
    {
        return a.time > b.time;
    }
};
priority_queue<ty> qu;
char map[N][N];
int visit[N][N];
int sx, sy, h, w, d;
const int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int Bfs()
{
    ty now, next;
    while(!qu.empty()) qu.pop();

    now.x = sx;
    now.y = sy;
    now.time = 1;

    qu.push(now);
    visit[sx][sy]=1;

    while(!qu.empty())
    {
        now = qu.top();
        qu.pop();

        for(int i = 0; i < 4;i++)
        {
            next.x = now.x + dir[i][0];
            next.y = now.y + dir[i][1];

            int x = next.x, y = next.y;
            if(x < 0 || x >= h || y < 0 || y >= w)
                return now.time;

            if(!visit[x][y] && map[x][y] != '#')
            {
                if(map[x][y] == '@') next.time = now.time + d + 1;
                    else next.time = now.time + 1;
                qu.push(next);
                visit[x][y] = 1;
            }
        }
    }
    return -1;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d", &h, &w, &d);
        for(int i = 0; i < h; i++)
        {
            for(int j = 0; j < w; j++)
            {
                scanf(" %c", &map[i][j]);
                if(map[i][j] == 'S')
                {
                    sx = i;
                    sy = j;
                }
            }
       }

        memset(visit, 0 ,sizeof(visit));
        printf("%d\n", Bfs());

    }
    return 0;
}