题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1044
题目大意:
在一个迷宫中,从起点走到终点,还有几个宝物,问在给定的时间内,到达终点后所能获取的最大价值。
思路:
先用bfs求出入口,宝物,出口,两两之间的最短距离。
在用dfs搜索所有情况,求出从入口走到出口能获得的最大价值。
熟悉两种搜索的优缺点:
BFS: 对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高
code:
View Code
1 # include<stdio.h> 2 # include<string.h> 3 # include<stdlib.h> 4 # include<queue> 5 using namespace std; 6 int dir[4][2]={1,0,-1,0,0,1,0,-1}; 7 int n,m,x0,y0,endx,endy,time,M,sum; 8 int val[12]; 9 int adj[13][13],vis[55][55],Max,visit[15]; 10 char map[55][55]; 11 struct node{ 12 int x,y,step; 13 }; 14 struct node1{ 15 int x,y; 16 }s[13]; 17 queue<node>q; 18 void bfs(int x1,int y1,int k) 19 { 20 int i,ans; 21 while(!q.empty()) q.pop(); 22 node cur,next; 23 cur.x=x1; 24 cur.y=y1; 25 cur.step=0; 26 q.push(cur); 27 memset(vis,0,sizeof(vis)); 28 vis[x1][y1]=1; 29 while(!q.empty()) 30 { 31 cur=q.front(); 32 q.pop(); 33 for(i=0;i<4;i++) 34 { 35 next.x=cur.x+dir[i][0]; 36 next.y=cur.y+dir[i][1]; 37 next.step=cur.step+1; 38 if(next.x<0 || next.x>=n || next.y<0 || next.y>=m || map[next.x][next.y]=='*' || vis[next.x][next.y]) continue; 39 vis[next.x][next.y]=1; 40 q.push(next); 41 if(map[next.x][next.y]>='A' && map[next.x][next.y]<='J') 42 { 43 ans=map[next.x][next.y]-'A'; 44 adj[k][ans]=adj[ans][k]=next.step; 45 } 46 else if(map[next.x][next.y]=='@') 47 { 48 adj[k][M]=adj[M][k]=next.step; 49 } 50 else if(map[next.x][next.y]=='<') 51 { 52 adj[k][M+1]=adj[M+1][k]=next.step; 53 } 54 } 55 } 56 } 57 void dfs(int i,int step,int value) 58 { 59 int j; 60 if(step>time || Max==sum) return;///Max==sum这一点很重要,不加这个剪枝就直接超时了,意思是在所有能够访问到的珠宝都捡到了的时候就返回,不在搜索了。 61 if(i==M+1) 62 { 63 if(value>Max) Max=value; 64 } 65 if(i!=M+1 && step+adj[i][M+1]>time) return; 66 for(j=0;j<=M+1;j++) 67 { 68 if(adj[i][j]!=-1) 69 { 70 if(visit[j]) continue; 71 visit[j]=1; 72 if(j<M) dfs(j,step+adj[i][j],value+val[j]); 73 else dfs(j,step+adj[i][j],value); 74 visit[j]=0; 75 } 76 } 77 } 78 int main() 79 { 80 int i,j,t,ncase; 81 scanf("%d",&ncase); 82 for(t=1;t<=ncase;t++) 83 { 84 if(t!=1) printf("\n"); 85 scanf("%d%d%d%d",&m,&n,&time,&M); 86 sum=0; 87 for(i=0;i<M;i++) 88 scanf("%d",&val[i]); 89 for(i=0;i<n;i++) 90 { 91 scanf("%s",map[i]); 92 for(j=0;j<m;j++) 93 { 94 if(map[i][j]=='@') {x0=i;y0=j;} 95 else if(map[i][j]=='<') {endx=i;endy=j;} 96 else if(map[i][j]>='A' && map[i][j]<='J') 97 { 98 s[map[i][j]-'A'].x=i; 99 s[map[i][j]-'A'].y=j; 100 } 101 } 102 } 103 memset(adj,-1,sizeof(adj)); 104 printf("Case %d:\n",t); 105 bfs(x0,y0,M);//入口用第M个点来表示 106 if(adj[M][M+1]==-1 || adj[M][M+1]>time) {printf("Impossible\n");continue;} 107 for(i=0;i<M;i++) 108 if(adj[i][M]!=-1) sum+=val[i]; 109 bfs(endx,endy,M+1);//出口用第M+1个点来表示 110 for(i=0;i<M;i++) 111 bfs(s[i].x,s[i].y,i); 112 Max=0; 113 memset(visit,0,sizeof(visit)); 114 visit[M]=1; 115 116 dfs(M,0,0); 117 printf("The best score is %d.\n",Max); 118 } 119 return 0; 120 }