问题链接:HDU1026 Ignatius and the Princess I。
题意简述:从矩阵的左上角走到右下角所需的最短时间,并且要求输出走的过程。矩阵中"."是可以走的,"X"是墙,n(数字1-9)是怪兽,需要战斗数字所示的时间。对于每个测试实例,先输入n和m,分别表示行数和列数,然后输入矩阵。
问题分析:显然求最短路径问题用BFS,另外由于有怪兽,所以搜索过程需要使用优先队列。一个典型的用分支限界法解决的问题。最小路径上每个点到出发点距离应该是最小的。
程序说明:用节点矩阵grid[][]存储输入的矩阵,同时存储输入的矩阵和到起始点需要行走的最少步骤,以及最小路径上前一个节点坐标。这个程序运行时间上算是比较短的。
AC的C++语言程序如下:
/* HDU1026 Ignatius and the Princess I */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <stack> using namespace std; #define DIRECTSIZE 4 struct direct { int drow; int dcol; } direct[DIRECTSIZE] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; const int MAXN = 100; const unsigned int MAXTIME = MAXN*MAXN*9+1; struct gridnode { char v; int prevrow, prevcol; unsigned int mintime; }; gridnode grid[MAXN+1][MAXN+1]; struct node { int row, col; unsigned int sumtime; bool operator<(const node n) const { return sumtime > n.sumtime; } }; int n, m; unsigned int mintime; node start, end2, f, v; int bfs() { int ans = 0; grid[0][0].prevrow = -1; grid[0][0].prevcol = -1; grid[0][0].mintime = 0; start.row = 0; start.col = 0; start.sumtime = 0; end2.row = n - 1; end2.col = m - 1; mintime = MAXTIME; priority_queue<node> q; q.push(start); while(!q.empty()) { f = q.top(); q.pop(); if(f.row == end2.row && f.col == end2.col) { if(f.sumtime < mintime) { mintime = f.sumtime; ans = 1; continue; } } if(f.sumtime >= mintime) continue; for(int i=0; i<DIRECTSIZE; i++) { int nextrow = f.row + direct[i].drow; int nextcol = f.col + direct[i].dcol; if(0 <= nextrow && nextrow < n && 0 <= nextcol && nextcol < m) { if(grid[nextrow][nextcol].v == '.') { // 曾经走过的点,这次时间长的话就不再走了 if(f.sumtime + 1 < grid[nextrow][nextcol].mintime) { v.row = nextrow; v.col = nextcol; v.sumtime = f.sumtime + 1; grid[v.row][v.col].mintime = v.sumtime; grid[v.row][v.col].prevrow = f.row; grid[v.row][v.col].prevcol = f.col; q.push(v); } } else if(grid[nextrow][nextcol].v != 'X') { v.sumtime = f.sumtime + 1; v.sumtime += grid[nextrow][nextcol].v - '0'; // 曾经走过的点,这次时间长的话就不再走了 if(v.sumtime < grid[nextrow][nextcol].mintime) { v.row = nextrow; v.col = nextcol; grid[v.row][v.col].mintime = v.sumtime; grid[v.row][v.col].prevrow = f.row; grid[v.row][v.col].prevcol = f.col; q.push(v); } } } } } return ans; } void output_print() { stack<node> s; node v1, v2; v.row = end2.row; v.col = end2.col; s.push(v); while(grid[v.row][v.col].prevrow != -1 || grid[v.row][v.col].prevcol != -1) { v2 = v; v.row = grid[v2.row][v2.col].prevrow; v.col = grid[v2.row][v2.col].prevcol; s.push(v); } printf("It takes %d seconds to reach the target position, let me show you the way.\n", mintime); int count = 0; v1 = s.top(); s.pop(); while(!s.empty()) { v2 = s.top(); s.pop(); printf("%ds:(%d,%d)->(%d,%d)\n", ++count, v1.row, v1.col, v2.row, v2.col); if(grid[v2.row][v2.col].v != '.') { for(int j=1; j<=grid[v2.row][v2.col].v-'0'; j++) printf("%ds:FIGHT AT (%d,%d)\n", ++count, v2.row, v2.col); } v1 = v2; } } char mygetchar() { char c; while((c = getchar()) && (c == ' ' || c == '\t' || c == '\n')); return c; } int main() { while(scanf("%d%d", &n, &m) != EOF) { for(int i=0; i<n; i++) for(int j=0; j<m; j++) { grid[i][j].v = mygetchar(); grid[i][j].mintime = MAXTIME; } int ans = bfs(); if(ans) output_print(); else printf("God please help our poor hero.\n"); printf("FINISH\n"); } return 0; }