参考博客:http://blog.csdn.net/ice_crazy/article/details/7763302
我的初学探索:
选择广搜:要求出最短时间。广搜的好处是(树)一层一层的向下进行(将一个结点的所有子结点加入一个先进先出的队列中),找到目标就可终止搜索。
选择优先队列:还是要求出最短时间。将所有可能结点加入队列后,我们希望每次弹出的都是用时最短的,这个最短不是路径最短(结点个数),而是因为需要打怪需要在某个结点停留一段时间。另外,优先队列需要自定义排序。
注意问题:1、走过的路要设为不可走的标记‘X’,不要忘了开始的位置。2、行至某个结点所用时间time用作优先队列的自定义排序。
打印路径:用dir表示4个方向,用flag作为路径的标记。flag[x][y]的值为走到(x,y)位置上的第i个方向(dir[i][]),每个位置至多走一次,所以它不存在覆盖,且可能走过的(包括不是最优的)都会有值,且在[0][0]的位置上值为0(初始值)。然后利用递归从终点向出发点找出路径,直到[0][0],即flag的值为初始值。由于方向dir的下标是从0开始的(flag的值也就包含了0),而我们把flag的初值设为了0,就会引发冲突,所以,对flag赋值时加1,使用时再减去1。
其它:1、fight表示打斗时间。2、细节上,一开始用map直接存打斗时间或0表示可走或-1表示不可走将会更好。
#include <iostream> #include <queue> using namespace std; int m, n; char map[102][102]; int dir[4][2]={1,0, 0,1, -1,0, 0,-1}; int flag[102][102]; int fight[102][102]; int totTime; struct Node{ int x; int y; int time; bool operator<(const Node &a) const { return a.time<time; } }; bool bfs() { priority_queue<Node>que; struct Node start; start.x=start.y=start.time=0; que.push(start); map[0][0]='X'; while (!que.empty()) { struct Node cur=que.top(); que.pop(); if(cur.x==n-1 && cur.y==m-1){ totTime=cur.time; return true; } for (int i=0; i<4; i++){ int xtmp=cur.x+dir[i][0]; int ytmp=cur.y+dir[i][1]; if(map[xtmp][ytmp]=='X') continue; if(xtmp<n && xtmp>=0 && ytmp<m && ytmp>=0 ){ struct Node nextstep; nextstep.x=xtmp; nextstep.y=ytmp; if(map[nextstep.x][nextstep.y]!='.') { nextstep.time=cur.time+1+map[nextstep.x][nextstep.y]-'0'; fight[nextstep.x][nextstep.y]=map[nextstep.x][nextstep.y]-'0'; } else nextstep.time=cur.time+1; flag[nextstep.x][nextstep.y]=i+1; que.push(nextstep); map[xtmp][ytmp]='X'; } } } return false;//没有到达,则返回false } int seconds; void printRoad(int x, int y) { if(flag[x][y]==0) return ; int pre_x, pre_y; pre_x=x-dir[flag[x][y]-1][0]; pre_y=y-dir[flag[x][y]-1][1]; printRoad(pre_x, pre_y); printf("%ds:(%d,%d)->(%d,%d)\n",seconds++,pre_x,pre_y,x,y); while(fight[x][y]--) printf("%ds:FIGHT AT (%d,%d)\n",seconds++,x,y); } int main(){ // freopen("D:/Documents/work/in.txt", "r", stdin); // freopen("D:/Documents/work/out.txt", "w", stdout); int i, j; while(~scanf("%d%d", &n, &m)) { memset(fight,0,sizeof(fight)); memset(flag,0,sizeof(flag)); for(i=0; i<n; i++) for(j=0; j<m; j++) cin>>map[i][j]; if(bfs()){ seconds=1; printf("It takes %d seconds to reach the target position, let me show you the way.\n",totTime); printRoad(n-1,m-1); } else { printf("God please help our poor hero.\n"); } printf("FINISH\n"); } return 0; }