題意:給一個迷宮,S,A,空格都可以走,問以最短步數走完全部S和A的最短路,把S和A看成點,先分別求出兩兩最短路,然後求最小生成樹。
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <iomanip>
using namespace std;
int w[102][102],node[55][55],n,m,cnt,dis[102][102];
char mapp[55][55];
bool visit[55][55];
int dre[4][2]={1,0,0,1,-1,0,0,-1};
const int inf=1000000;
struct point
{
int x,y,num;
};
void bfs(int x,int y)
{
memset(visit,0,sizeof(visit));
queue<point>q;
point p;
p.x=x;
p.y=y;
p.num=node[x][y];
q.push(p);
visit[x][y]=1;
memset(dis,inf,sizeof(dis));
dis[p.x][p.y]=0;
while(!q.empty())
{
point temp=q.front();
q.pop();
if(temp.num)
w[p.num][temp.num]=dis[temp.x][temp.y];
for(int i=0;i<4;i++)
{
int ix=temp.x+dre[i][0];
int iy=temp.y+dre[i][1];
if(ix<0||ix>=n||iy<0||iy>=m)continue;
if(!visit[ix][iy]&&mapp[ix][iy]!='#')
{
dis[ix][iy]=dis[temp.x][temp.y]+1;
point cur;
cur.x=ix;
cur.y=iy;
cur.num=node[ix][iy];
q.push(cur);
visit[ix][iy]=1;
}
}
}
return ;
}
int prim()
{
int zx[102];
memset(zx,0,sizeof(zx));
int low_dis[102];
memset(low_dis,inf,sizeof(low_dis));
int len=0,sum=1;
int len1,p;
int s=1;
zx[s]=1;
while(sum!=cnt)
{
len1=inf;
for(int j=2;j<=cnt;j++)
{
if(!zx[j]&&w[s][j]<low_dis[j])
{
low_dis[j]=w[s][j];
}
if(!zx[j]&&len1>low_dis[j])
{
len1=low_dis[j];
p=j;
}
}
s=p;
zx[s]=1;
sum++;
len+=len1;
}
return len;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>m>>n;
char temp[55];
gets(temp);
cnt=0;
memset(node,0,sizeof(node));
for(int i=1;i<=n;i++)
{
gets(mapp[i]);
for(int j=1;j<=m;j++)
{
if(mapp[i][j]=='S'||mapp[i][j]=='A')
{
node[i][j]=++cnt;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(node[i][j])
bfs(i,j);
cout<<prim()<<endl;
}
return 0;
}