HDU 1026 BFS+优先队列

416 阅读2分钟

HDU 1026 Ignatius and the Princess I

就是简单的广搜走迷宫找最短路径,不过每次路径不单单是走的距离,还有格子上杀怪的时间,所以可以利用优先队列,按到达某个节点已经消耗的时间排序,逐个取出来广搜。

另外题目还要求最后输出最短路径,可以用一个和迷宫一样的数组,保存每个点上一步的节点,这样BFS结束后,从终点往前找,并压入栈中,一直到起点位置。然后按时间序列输出,当时间小于该点应消耗的时间时,说明在这点上打怪了,按题目输出即可。

其实现在感觉这题写的有点杂乱。。。不过好歹是自己难得一次过的BFS。。。

AC代码:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<stack>
using namespace std;

int n, m;
char matrix[105][105];
bool vis[105][105] = {false};
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

struct Node{
    int x, y;
    int steps;

    Node(){}
    Node(int x, int y, int steps){
        this->x = x;
        this->y = y;
        this->steps = steps;
    }

    bool operator<(const Node& o) const{
        return this->steps >= o.steps;
    }

    void show(){
        cout << "(" << x << "," << y << ")";
    }
};

void bfs();
void showPath(int s);
bool isLegal(int x, int y);

Node dp[105][105];

int main(void)
{
    freopen("in.txt", "r", stdin);

    while(cin >> n >> m)
    {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                cin >> matrix[i][j];
        
        memset(vis, 0, sizeof(vis));
        memset(dp, 0, sizeof(dp));

        bfs();
        cout << "FINISH" << endl;
    }

    return 0;
}

void bfs()
{
    priority_queue<Node> q;
    q.push(Node(0, 0, 0));
    vis[0][0] = true;

    while(!q.empty())
    {
        Node node = q.top();
        q.pop();

        if(node.x == n-1 && node.y == m-1){  //Find the target
            cout << "It takes " << node.steps << " seconds to reach the target position, let me show you the way." << endl;
            showPath(node.steps);
            return;
        }

        for(int i = 0; i < 4; i++)  //BFS for up & down & left & right, to find Reachable Point
        {
            int xx = node.x + dx[i];
            int yy = node.y + dy[i];

            if(isLegal(xx, yy)) //judge if the point is legal
            {
                vis[xx][yy] = true;

                int newStep = node.steps + 1;
                if(matrix[xx][yy] != '.')              //account for the time fighting monster
                    newStep += matrix[xx][yy] - 48;
                Node newNode(xx, yy, newStep);

                dp[xx][yy] = node;
                q.push(newNode);
            }
        }
    }

    cout << "God please help our poor hero." << endl;
    return;
}

void showPath(int s)
{
   int x = n-1;
   int y = m-1;
   Node curNode(x, y, s);   //end point
   stack<Node> stack;
   while(x != 0 || y != 0)
   {
       stack.push(curNode);     //push into stack reversely
       curNode.x = dp[x][y].x;
       curNode.y = dp[x][y].y;
       curNode.steps = dp[x][y].steps;
       x = curNode.x;
       y = curNode.y;
   }
    stack.push(Node(0, 0, 0));

    curNode = stack.top();
    stack.pop();
    for(int i = 1; i <=s; i++)
    {
        cout << i << "s:";
        curNode.show();
        cout << "->";

        curNode = stack.top();
        stack.pop();
        curNode.show();
        cout << endl;

        for(int j = i + 1; j <= curNode.steps; j++)     //Fighting monster
        {
            cout << j << "s:";
            cout << "FIGHT AT ";
            curNode.show();
            cout << endl;
            i = j;
        }
    }
}

bool isLegal(int x, int y)
{
    if(x < 0 || y < 0 || x >= n || y >= m || vis[x][y] || matrix[x][y] == 'X')
        return false;
    return true;
}