题目链接:http://poj.org/problem?id=3026
题意:
外星人从S出发去寻找A,外星人只有在两种情况下才会分成多组,同时去寻找其他外星人,第一种情况是从S出发的时候会分成多组,第二种是在找到A的情况下分成多组;分成的多组外星人中可以让多组同时走,也可以让某几个不走,留在原地,计算的总距离就是移动过的外星人走过的路得总和;比如说 一个A的左边2个单位有一个A,右边3个单位有一个A,那么我们可以分成两组,一左一右,左边走两步,右边走三步,那么步数就是3+2;还有一种情况就是, A只有左边有一个A,那么你可以不分组(题目说至少分二个,但是分出来的那个你可以让它留在原地不走)直接往左走;(注意:分组过后的步数是从0开始计数的)
思路:
把S作为根节点连接其他A,会发现,只有当这个树是一个最小生成树的时候,总距离是最小的;可以用BFS求出点每个A到其他点的点A或者S的距离,然后用prim求出最小生成树的值;
坑点:输入的时候用get()吃掉空格 和回车,以前都是习惯性用getchar()吃回车的,不知道为什么不行,下次就统一用gets吧;
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int Maxn = 55;
const int INF = 0x3f3f3f3f;
struct Node {
int x,y,step;
};
int G[Maxn*Maxn][Maxn*Maxn],used[Maxn][Maxn],vis[Maxn*Maxn],cost[Maxn*Maxn],node,Bvis[Maxn][Maxn];
int dist[5][2]= {{-1,0},{0,1},{1,0},{0,-1}},n,m; // 上右下左
char mp[Maxn][Maxn];
void prim () {
for (int i = 1; i <= node; ++i) {
vis[i] = 0;
cost[i] = INF;
}
int ans = 0; cost[1] = 0;
while (1) {
int v = -1;
for (int u = 1; u <= node; ++u) {
if(!vis[u] && (v == -1 || cost[u] < cost[v])) v = u;
}
if(v == -1) break;
vis[v] = 1; ans+=cost[v];
for (int u = 1; u <= node; ++u) {
if(!vis[u] && G[u][v] != INF) {
cost[u] = min (cost[u],G[u][v]);
}
}
}
printf("%d\n",ans);
}
void bfs (int xx, int yy, int sNode) {
memset(Bvis,0,sizeof(Bvis));
queue<struct Node> qu;
Node p,tmp,start; start.x = xx; start.y = yy; start.step = 0;
qu.push(start); Bvis[xx][yy] = 1;
while (!qu.empty()) {
p = qu.front(); qu.pop();
for (int i = 0; i < 4; ++i) {
tmp.x = p.x + dist[i][0]; tmp.y = p.y + dist[i][1];
tmp.step = p.step + 1;
if(tmp.x > 0 && tmp.x <= m && tmp.y >= 0 && tmp.y < n &&
!Bvis[tmp.x][tmp.y] && mp[tmp.x][tmp.y] != '#') {
if(mp[tmp.x][tmp.y] == 'A' || mp[tmp.x][tmp.y] == 'S') {
if(!used[tmp.x][tmp.y]) used[tmp.x][tmp.y] = ++node;
int sN = used[tmp.x][tmp.y];
G[sN][sNode] = tmp.step;
G[sNode][sN] = tmp.step;
}
Bvis[tmp.x][tmp.y] = 1;
qu.push(tmp);
}
}
}
}
void init () {
node = 0;
for (int i = 1; i <= Maxn*Maxn; ++i) {
for (int j = 1; j <= Maxn*Maxn; ++j) {
if(i == j) G[i][j] = 0;
else G[i][j] = INF;
}
}
memset(used,0,sizeof(used));
memset(mp,0,sizeof(mp));
}
int main(void)
{
int t;
char tmp[200];
scanf("%d",&t);
while (t--) {
scanf("%d%d",&n,&m);
gets(tmp);
init ();
for (int i = 1; i <= m; ++i) {
gets(mp[i]);
}
for (int i = 1; i <= m; ++i) {
for (int j = 0; j < n; ++j) {
if(mp[i][j] == 'A') {
if(!used[i][j]) used[i][j] = ++node;
bfs (i,j,used[i][j]);
}
}
}
prim ();
}
return 0;
}