HDOJ 1026 Ignatius and the Princess I 解题

来源:互联网 发布:易语言钩子注入源码 编辑:程序博客网 时间:2024/05/20 20:44

HDOJ 1026 解题 http://acm.hdu.edu.cn/showproblem.php?pid=1026

题目不难,属于基本的广度优先搜索题。只是需要输出路径,比较麻烦。深度优先搜索的路径可以直接写出来,而广度优先搜索的路径需要用一个表来保存,这里借鉴了别人写的程序。具体内容已经在注释里写的很清楚了。

/*******************************************\    HDOJ 1026 Ignatius and the Princess I    寻找迷宫最短路径,记忆化广度优先搜索    author: Sail\*******************************************/#include <iostream>#include <queue>#include <memory.h>using namespace std;char maze[101][101]; //迷宫bool visited[101][101]; //访问标记int n,m;int stepx[4] = {0, 1, 0, -1}; //left down right upint stepy[4] = {-1, 0, 1, 0}; //左 下 右 上 搜索下一节点步长int depth;//走过路径长度,即到达终点的时间struct point{    int x;    int y;    int hp;    int step;};point path[102][102]; //用来保存路径,path[x][y] 中保存的是上一个到达此点的节点queue<point> q;  //广搜队列bool isBound(point p) {     if (p.x<0 || p.y<0 || p.x>=n || p.y>=m)     {         return false;     }     return true; }//参考别人写的,保存路径,path[x][y] 中保存的是上一个到达此点的节点 void outputPath(int x, int y, int hp) {     if(path[x][y].x + path[x][y].y != 0) //从(0,0)开始输出        outputPath(path[x][y].x,path[x][y].y,path[x][y].hp);     int px = path[x][y].x;     int py = path[x][y].y;     cout << depth++ << "s:(" << px << "," << py << ")->(" << x << "," << y << ")" << endl;     for(int i=1 ; i<=hp; ++i)        cout << depth++ << "s:FIGHT AT ("<< x << "," << y << ")" << endl; }///广度优先搜索,查找最佳路径。这里这样处理:由于怪物的存在,破坏了广度优先搜索的结构,因此每次经过怪物时,将hp-1,再将值赋给///这一点,并将此点入队列,并不直接进行扩展,直到hp减为0后,将这一点设置为'.'即一般路径,进行扩展,这样能够保证同一层次找到的///第一个解即为最优解(因为这样处理后,所有扩展的节点代价都相等都为1)void BFS(){    bool rescue = false;    point curr, next;    curr.x = 0;curr.y=0;curr.step=0;curr.hp=0; //初始化起始位置    q.push(curr);    visited[0][0]=true;    while(!q.empty())    {        curr = q.front();        q.pop();        if(curr.x == n-1 && curr.y == m-1 && maze[curr.x][curr.y]=='.') //找到出口,则输出结果        {            rescue = true;            cout << "It takes " << curr.step << " seconds to reach the target position, let me show you the way." << endl;            //输出路径            depth = 1;            outputPath(curr.x,curr.y,curr.hp);        }        //若碰到怪兽,则将其hp-1并赋给这个点,不进行扩展直接入队列        if(maze[curr.x][curr.y] >= '1' && maze[curr.x][curr.y] <= '9')        {            int tmp = maze[curr.x][curr.y] - '1';            if(tmp == 0)                maze[curr.x][curr.y] = '.';            else                maze[curr.x][curr.y] = tmp + '0';            curr.step++; //记录打怪兽时间,一滴一滴的打            q.push(curr);        }        else //普通节点,进行扩展,        {            //朝着左下右上四个方向进行扩展            for(int i=0 ; i<4 ; ++i)            {                next.x = curr.x + stepx[i];                next.y = curr.y + stepy[i];                next.step = curr.step + 1;                //如果没有访问过,且不是边界,且不是墙,则将路径保存起来                if(visited[next.x][next.y]==false && isBound(next) && maze[next.x][next.y]!='X')                {                    visited[next.x][next.y] = true;                    //输出路径不会,参考别人的方法保存搜索的路径                    path[next.x][next.y].x = curr.x;                    path[next.x][next.y].y = curr.y;                    path[next.x][next.y].hp = curr.hp;                    //更新路径的血量(这样处理为了通用性,将怪兽点与路径点用同样方式处理,对怪兽点的扩展按照上面if方法)                    if(maze[next.x][next.y] == '.')                        next.hp = 0;                    else                        next.hp = maze[next.x][next.y] - '0';                    q.push(next);                }            }        }    }    if(!rescue) //若没有找到路径    {        cout << "God please help our poor hero." << endl;    }}int main(){    while(cin >> n >> m)    {        //构造迷宫并初始化visited        for(int i=0 ; i<n ; ++i)        {            for(int j=0 ; j<m ; ++j)            {                cin >> maze[i][j];                visited[i][j] = false;            }        }        memset(path,0, sizeof(path)); //初始化path路径数组        BFS();        cout << "FINISH" << endl;    }    return 0;}