原题链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1815
分析题意可知,这是一道变形的最短路径问题,通过寻找总作战次数最少的路线来求出最终结果
通过广度搜索加上贪心算法的思维来求出答案。其中为了优化搜索时间,使用了优先队列的贪心思维,而不使用优先队列的话,可能面临超时的问题,且会大大增加算法的复杂度。
个人源代码:
#include <iostream> #include <cstdio> #include <queue> using namespace std; int cla_s[26]; //记录大写字母对应的战斗次数 char a[1005][1005]; //记录矩阵 bool visited[1005][1005]; //标记是否进行过访问 int dire[4][2] = { {-1,0},{1,0},{0,-1},{0,1} }; //四个方向 ,上下左右 int n,m; //矩阵的行数和列数 struct node { int x,y; //节点坐标 long long co; //记录着走到当前结点的最少战斗次数 }; bool operator<(const node &a,const node &b) { //运算符重载,便于使用优先队列 return a.co>b.co; } node sta; //开始结点 bool is_band(node a) { //判断当前结点是否是边界 if (a.x==1 || a.x==n) return true; if (a.y==1 || a.y==m) return true; return false; } void BFS() { //广度搜索算法函数 node cur,pre; priority_queue<node> q; //优先队列,根据重载的运算符进行排序 sta.co=0; visited[sta.x][sta.y]=true; q.push(sta); while (!q.empty()) { pre=q.top(); q.pop(); if (is_band(pre)) { printf("%lld\n",pre.co); break; } for (int i=0; i<4; i++) { cur.x=pre.x+dire[i][0]; cur.y=pre.y+dire[i][1]; if (cur.x<1 || cur.x>n || cur.y<1 || cur.y>m) continue; //当前结点越界,跳过 cur.co=pre.co+cla_s[a[cur.x][cur.y]-'A']; //更行当前的结点战斗次数 if (visited[cur.x][cur.y]) continue; visited[cur.x][cur.y] = true; q.push(cur); } } } int main() { int T; cin>>T; char cls; int tim; char ss[1010]; while (T--) { int c; scanf ("%d%d%d",&c,&m,&n); while (c--) { cin>>cls>>tim; cla_s[cls-'A'] = tim; } for (int i=1; i<=n; i++) { scanf ("%s",ss); for (int j=1; j<=m; j++) { a[i][j] = ss[j-1]; visited[i][j]=false; if (a[i][j]=='E') { sta.x=i; sta.y=j; } } } BFS(); } return 0; }