Borg Maze (bfs+最小生成树)

本文介绍了一种解决迷宫中捕捉所有外星人问题的方法,通过使用宽度优先搜索(BFS)确定各点间的最短距离,并利用Prim算法计算最小生成树来找出最短路径。

题目大概:

在迷宫里抓住所有外星人的最佳方式。

思路:

用bfs()求出所有点(包括S和所有A)之间的最短距离,再用prim最小生成树求出最短路的距离。


代码:
  1. #include <iostream>  
  2. #include <string>  
  3. #include <cstdio>  
  4. #include <queue>  
  5. #include <cstring>  
  6. #include <algorithm>  
  7. const int INF = 0x3f3f3f3f;  
  8. using namespace std;  
  9. int n,pp;  
  10. char map[55][55];  
  11. int vis[55][55],p[250][250],a[250][250],b[250],vi[250];  
  12. int x,y,x1,y1;  
  13. int dx[4]={0,0,1,-1};  
  14. int dy[4]={1,-1,0,0};  
  15.   
  16. struct poin  
  17. {  
  18.     int s,d,tt;  
  19. };  
  20.   
  21. int bfs(int w,int e)  
  22. {  
  23.     poin t;  
  24.     t.s=w;t.d=e;t.tt=0;  
  25.     queue<poin>q;  
  26.     vis[t.s][t.d]=1;  
  27.     q.push(t);  
  28.     poin w1,w2;  
  29.     while(!q.empty())  
  30. {    w1=q.front();  
  31.      q.pop();  
  32.      if(map[w1.s][w1.d]=='S'||map[w1.s][w1.d]=='A'){  
  33.              a[p[w][e]][p[w1.s][w1.d]]=w1.tt;  
  34.              a[p[w1.s][w1.d]][p[w][e]]=w1.tt;}  
  35.      for(int i=0;i<4;i++)  
  36.      {  
  37.          w2.s=w1.s+dx[i];  
  38.          w2.d=w1.d+dy[i];  
  39.   
  40.          if(w2.s>=0&&w2.s<y&&w2.d>=0&&w2.d<x&&map[w2.s][w2.d]!='#'&&!vis[w2.s][w2.d])  
  41.          {  
  42.   
  43.              vis[w2.s][w2.d]=1;  
  44.              w2.tt=w1.tt+1;  
  45.              q.push(w2);  
  46.   
  47.          }  
  48.   
  49.      }  
  50.   
  51.   
  52. }  
  53.   
  54. }  
  55.   
  56. int prim(int qq)  
  57. {  
  58.     memset(vi,0,sizeof(vi));  
  59.     for(int i=1;i<pp;i++)  
  60.     b[i]=a[qq][i];  
  61.     int sum=0;  
  62.     vi[qq]=1;  
  63.     for(int i=2;i<pp;i++)  
  64.     {   int k=i,minn=INF;  
  65.         for(int j=1;j<pp;j++)  
  66.         {  
  67.             if(!vi[j]&&minn>b[j])  
  68.             {  
  69.                 minn=b[j];  
  70.                 k=j;  
  71.             }  
  72.         }  
  73.         sum+=minn;  
  74.         vi[k]=1;  
  75.         for(int j=1;j<pp;j++)  
  76.         {  
  77.             if(!vi[j]&&b[j]>a[k][j])  
  78.             {  
  79.                 b[j]=a[k][j];  
  80.             }  
  81.         }  
  82.   
  83.     }  
  84.     return sum;  
  85.   
  86. }  
  87.   
  88. int main()  
  89. {  
  90.      scanf("%d",&n);  
  91.     for(int i=1;i<=n;i++)  
  92.     {  
  93.         scanf("%d%d\n",&x,&y);  
  94.         pp=1;  
  95.   
  96.         for(int j=0;j<y;j++)  
  97.         {  
  98.             gets(map[j]);  
  99.             for(int k=0;k<x;k++)  
  100.             {  
  101.                 if(map[j][k]=='S'||map[j][k]=='A'){  
  102.                 p[j][k]=pp;  
  103.                 pp++;  
  104.                 }  
  105.             }  
  106.         }  
  107.   
  108.   
  109.   
  110.         for(int i=0;i<=pp;i++)  
  111.         {  
  112.             for(int j=0;j<=pp;j++)  
  113.             {  
  114.                 if(i==j){a[i][j]=0;}  
  115.                 else a[i][j]=INF;  
  116.             }  
  117.         }  
  118.   
  119.            for(int i=0;i<y;i++)  
  120.         {  
  121.             for(int j=0;j<x;j++)  
  122.             {  
  123.                if(map[i][j]=='S'||map[i][j]=='A')  
  124.                {memset(vis,0,sizeof(vis));  
  125.                    bfs(i,j);  
  126.   
  127.                }  
  128.             }  
  129.         }  
  130.   
  131.         cout<<prim(1)<<endl;  
  132.     }  
  133.   
  134.     return 0;  
  135. }  


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值