思路:
- 最小生成树+BFS
- 自己想出来哒,但是数据好坑,输入长宽后有一大堆空格,WA 的好难受。感谢CMyDreamer的BLOG。
- 题目很麻烦,依次需要读图,存图,BFS 枚举每两个点之间的最短路径,Prim 求以 S 为根的最小生成树。还用到了两种结构体两个优先队列,分别用于 BFS 和 Prim。
- 可以使用 map 优化查找。我没有写。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 105;
int N,M;
int ans;
int dis[maxn];
bool vis[maxn];
bool book[maxn][maxn];
char mp[maxn][maxn];
const int mt[4][2] = {1,0 , 0,1 , -1,0 , 0,-1} ;
int W[maxn][maxn];
struct ORD{
int x;
int y;
}ord[maxn];int cnt;
struct NODE{
int id;
int dis;
friend bool operator > (NODE a , NODE b)
{
return a.dis > b.dis;
}
NODE(int id,int dis) : id(id) , dis(dis) {} ;
};
priority_queue <NODE , vector<NODE> , greater<NODE> > Q;
struct GRID{
int x,y;
int step;
friend bool operator > (GRID a,GRID b)
{
return a.step > b.step;
}
GRID(int x,int y,int step) : x(x) , y(y) , step(step) {} ;
};
priority_queue <GRID , vector<GRID> , greater<GRID> > q;
void INIT(){
ans = 0;
cnt = 0;
memset(W , 0 , sizeof(W));
memset(vis , 0 , sizeof(vis));
memset(dis , INF , sizeof(dis));
return ;
}
bool check(int x,int y){
if(x < 1 || x > M || y < 1 || y > N || mp[x][y] == '#')
return false;
return true;
}
void BFS(int s){
memset(book , 0 , sizeof(book));
q.push(GRID(ord[s].x , ord[s].y , 0));book[ord[s].x][ord[s].y] = true;
while(q.size()){
GRID cur = q.top() ; q.pop() ;
int x = cur.x;
int y = cur.y;
if(mp[x][y] == 'A'){
int i;
for(i = 1;i <= cnt;i++)
if(ord[i].x == x && ord[i].y == y)
break;
W[s][i] = W[i][s] = cur.step;
}
for(int i=0;i<4;i++){
int nx = x + mt[i][0];
int ny = y + mt[i][1];
if(check(nx,ny) && !book[nx][ny]){
book[nx][ny] = true;
q.push(GRID(nx,ny,cur.step+1));
}
}
}
return ;
}
void PRIM(){
dis[0] = 0;
Q.push(NODE(0 , 0));
while(Q.size()){
NODE cur = Q.top() ; Q.pop() ;
int id = cur.id;
if(vis[id])
continue;
ans += dis[id];
vis[id] = true;
for(int i=1;i<=cnt;i++)
if(!vis[i] && dis[i] > W[id][i]){
dis[i] = W[id][i];
Q.push(NODE(i , dis[i]));
}
}
return ;
}
int main(){
int T;cin>>T;
while(T--){
INIT();
cin>>N>>M;
char gar[maxn];
gets(gar);
for(int i=1;i<=M;i++){
for(int j=1;j<=N;j++){
char ch = mp[i][j] = getchar();
if(ch == 'A'){
++cnt;
ord[cnt].x = i;
ord[cnt].y = j;
}
if(ch == 'S'){
ord[0].x = i;
ord[0].y = j;
}
}
getchar();
}
for(int i=0;i<=cnt;i++)
BFS(i);
PRIM();
cout<<ans<<endl;
}
return 0;
}