题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1044
题目大意:
在一个迷宫中,从起点走到终点,还有几个宝物,问在给定的时间内,到达终点后所能获取的最大价值。
题目思路:
我们要解决几个问题:1、求入口到第一个取宝物的地方的最短距离
2、求第i个取宝物的地方到第i+1个取宝物的地方的最短距离
3、求第n个取宝物的地方到出口的最短距离
4、保证以上3点能在时间L内实现的情况下,取得的宝石价值最大
BFS特点:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元来存储状态)
DFS特点:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高
所以,我们先用BFS求出入口、各宝物堆、出口两两间的最短距离,然后用DFS利用BFS求出的两两最短距离(保证耗时最小)求出在时间L内到达出口且取得最大价值宝物堆的路径。
#include<iostream> #include <queue> #include<string.h> using namespace std; int n,m,t,w; int val[60]; char map[60][60]; int vis[60][60],vis2[60],step[60][60]; queue<int> q; int d[4][2]={-1,0,1,0,0,-1,0,1}; int abc[60][60],ans,sum; //abc[i][j]用来存i到j的最短距离 void bfs(int x, int y , int s) //x,y表示abc[][]中的i的坐标,s代表i的性质(是入口?第几个宝物堆?还是出口) { while(!q.empty()) q.pop(); int u=x*m+y; q.push(u); vis[x][y]=1; step[x][y]=0; while(!q.empty()) { u = q.front(); q.pop(); x = u/m ; y = u%m; for(int i=0;i<4;i++) { int xx = x+d[i][0] , yy = y+d[i][1]; if(xx<0||xx>=n||yy<0||yy>=m) continue; if(vis[xx][yy]==0 && map[xx][yy]!='*') { vis[xx][yy]=1; step[xx][yy]=step[x][y]+1; if(map[xx][yy]=='@') abc[s][0]=step[xx][yy]; if(isalpha(map[xx][yy])) {abc[s][map[xx][yy]-64]=step[xx][yy]; } if(map[xx][yy]=='<') abc[s][w+1]=step[xx][yy]; q.push(xx*m+yy); } } } } void dfs(int p , int s , int time) { //p表示a[][]中i的性质 ,s表示当前搜索路径可得的宝石价值,time表示当前搜索路径的时间 if(time>t || ans==sum) return; if(p>w && s > ans) ans = s ; //p>w说明这一个深搜路径搜到了底(出口) for(int i=0;i<=w+1; i++) { if(abc[p][i]==0 || vis2[i]) continue; vis2[i]=1; dfs(i , s+val[i] , time + abc[p][i]); vis2[i]=0; } } int main() { int c , x=0; scanf("%d",&c); while (c--) { memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); memset(abc,0,sizeof(abc)); sum=0; ans=-1; scanf("%d%d%d%d",&m,&n,&t,&w); val[0]=val[w+1]=0; for(int i=1;i<=w;i++) scanf("%d",&val[i]) , sum +=val[i]; for(int i=0;i<n;i++) scanf("%s",map[i]); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { memset(step,0,sizeof(step)); memset(vis,0,sizeof(vis)); //这两个赋初值0,因为abc[][]中i(定)与j(变)就会将几乎所有格子遍历一遍 if(map[i][j]=='@') bfs(i,j,0); if(isalpha(map[i][j])) bfs(i,j,map[i][j]-64); if(map[i][j]=='<') bfs(i,j,w+1); } vis2[0]=1; dfs(0,0,0); printf("Case %d:\n",++x); if(ans>=0) printf("The best score is %d.\n",ans); else printf("Impossible\n"); if(c) printf("\n"); } return 0; }