HDU 1044(bfs+dfs)


题意:

在一个迷宫中,从起点走到终点,还有几个宝物,问在给定的时间内,到达终点后所能获取的最大价值。

题目思路:

我们要解决几个问题: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;
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值