hdu 1044 Collect More Jewels

题目链接: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 }

 

转载于:https://www.cnblogs.com/183zyz/archive/2012/04/27/2473294.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值