題意:從S出發,去抓每一個A,求總路徑最短長度。在S點和A點人可以分身成2人,不過一次只能讓一個人走。
思路是先利用BFS求出各點之間的距離,建成圖,再套用最小生成樹模板。
一次性A了。不過覺得在判斷第幾個編號的點時稍顯麻煩了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int inf=1000000;
const int maxn=205;
char mapp[maxn][maxn];
bool visit[maxn][maxn];
bool vis[maxn];
int dx[]= {-1,0,1,0}; //四個方向
int dy[]= {0,-1,0,1};
int mat[maxn][maxn],dis[maxn];
int cou,ans;
struct Node
{
int x;
int y;
int s; //記錄距離
int num; //點的編號
} next,nodes[maxn]; //nodes[]存所有的點
void bfs(Node node,int a)
{
memset(visit,0,sizeof(visit));
node.s=0;
mapp[node.y][node.x]=' '; //訪問過後將'S'或'A'變成' ',下次不需重復訪問
queue<Node>q;
visit[node.x][node.y]=true;
q.push(node);
while(!q.empty())
{
node=q.front();
if(mapp[node.y][node.x]=='A')
{
if(a==0)
{
nodes[cou]=node;
mat[a][cou]=mat[cou][a]=node.s;
cou++; //記錄有多少個點
}
else
{
int b;
for(int j=0;; j++)
if(nodes[j].x==node.x && nodes[j].y==node.y)
{
b=nodes[j].num;
break;
}
mat[a][b]=mat[b][a]=node.s; //將距離寫入對角矩陣
}
}
q.pop();
for(int i=0; i<4; i++)
{
next=node;
next.x=node.x+dx[i];
next.y=node.y+dy[i];
if(!visit[next.x][next.y] && (mapp[next.y][next.x]==' ' || mapp[next.y][next.x]=='A'))
{
visit[next.x][next.y]=true;
next.s=node.s+1;
q.push(next);
}
}
}
return ;
}
bool prim()
{
memset(vis,0,sizeof(vis));
for(int i=0;i<cou;i++)
dis[i]=(i==0? 0:inf);
ans=0;
for(int i=0;i<cou;i++)
{
int temp=inf,k=0;
for(int j=0;j<cou;j++)
{
if(!vis[j] && dis[j]<temp )
{
temp=dis[j];
k=j;
}
}
if(temp==inf)
return false;
vis[k]=true;
ans+=temp;
for(int j=0;j<cou;j++)
{
if(!vis[j] && dis[j]>mat[k][j])
dis[j]=mat[k][j];
}
}
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
while(n--)
{
int x,y;
memset(mapp,0,sizeof(mapp));
scanf("%d%d",&x,&y);
char c[maxn]={0};
gets(c);
for(int i=0; i<y; i++)
gets(mapp[i]);
for(int i=0; i<x; i++)
for(int j=0; j<y; j++)
if(mapp[i][j]=='S')
{
nodes[0].y=i;
nodes[0].x=j;
}
bool flag=true;
cou=1;
for(int i=0; i<cou; i++)
{
bfs(nodes[i],i);
if(flag)
{
for(int j=0; j<cou; j++)
nodes[j].num=j; //給各個點編號,只運行一次
flag=false;
}
}
prim();
printf("%d\n",ans);
}
return 0;
}