链接:
http://poj.org/problem?id=3026
题意: 有一个名叫Borg的种族,他们很团结,时刻联系在一起。他们现在要消灭A外星人。S是他们的出发点,Borg是一个集体,可以分散成多个小团体。他们在遇到一个A外星人后,就又可以分散成多个小团体,从而继续消灭其它的外星人,直至所有的A外星人被消灭。然后,求这些Borg消灭所有的A外星人所需要走过的最短路程(指各个分散的小团体所走过的所有路程的和)。用一个矩阵来表示这么一个空间,其中‘#’表示墙壁不能走,空格‘ ’是可走的空间。
浅谈:其实就是要求Borg这个团体所能形成的一个最小生成树(因为他们是相互联系的,和最小生成树的结构一样)。然后,另一个关键就是求出S和各个A,A和各个A之间的距离。,然后再用最小生成树求最短路程。算法就是BFS+Prim。
题意: 有一个名叫Borg的种族,他们很团结,时刻联系在一起。他们现在要消灭A外星人。S是他们的出发点,Borg是一个集体,可以分散成多个小团体。他们在遇到一个A外星人后,就又可以分散成多个小团体,从而继续消灭其它的外星人,直至所有的A外星人被消灭。然后,求这些Borg消灭所有的A外星人所需要走过的最短路程(指各个分散的小团体所走过的所有路程的和)。用一个矩阵来表示这么一个空间,其中‘#’表示墙壁不能走,空格‘ ’是可走的空间。
浅谈:其实就是要求Borg这个团体所能形成的一个最小生成树(因为他们是相互联系的,和最小生成树的结构一样)。然后,另一个关键就是求出S和各个A,A和各个A之间的距离。,然后再用最小生成树求最短路程。算法就是BFS+Prim。
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#define MAX 250
#define cMAX 2550
#define INF 99999
using namespace std;
struct creature
{
char c;
int a,b,num;
int path;
};
struct mazcre
{
char c;
int num;
}cre[MAX][MAX];
int visit[MAX][MAX];
int steps[cMAX][cMAX];
int lowcost[cMAX];
int closest[cMAX];
int k,max_num,s_start;
void Pathcount_bfs(creature s)//BFS算法
{
queue<creature> q;
int begin=s.num;//把这个生物的编号记为begin,是下面每次记录steps[begin][j]的起始点
creature now;
now.c=s.c;
now.path=s.path;
now.num=s.num;
now.a=s.a;
now.b=s.b;
q.push(now);
visit[now.a][now.b]=1;
while(!q.empty())
{
now=q.front();
q.pop();
if(cre[now.a-1][now.b].c!='#'&&!visit[now.a-1][now.b])
{
visit[now.a-1][now.b]=1;
creature temp;
temp.c=cre[now.a-1][now.b].c;
temp.a=now.a-1;
temp.b=now.b;
temp.path=now.path+1;
temp.num=now.num;
if(cre[now.a-1][now.b].c=='A'||cre[now.a-1][now.b].c=='S')
{
temp.num=cre[now.a-1][now.b].num; //如果是生物A或S,则把cre[i][j]存储的num拿出来
steps[begin][temp.num]=temp.path; //有了前面编号的记录就很好对steps赋值了
}
q.push(temp);
}
if(cre[now.a+1][now.b].c!='#'&&!visit[now.a+1][now.b])
{
visit[now.a+1][now.b]=1;
creature temp;
temp.c=cre[now.a+1][now.b].c;
temp.a=now.a+1;
temp.b=now.b;
temp.path=now.path+1;
temp.num=now.num;
if(cre[now.a+1][now.b].c=='A'||cre[now.a+1][now.b].c=='S')
{
temp.num=cre[now.a+1][now.b].num;
steps[begin][temp.num]=temp.path;
}
q.push(temp);
}
if(cre[now.a][now.b-1].c!='#'&&!visit[now.a][now.b-1])
{
visit[now.a][now.b-1]=1;
creature temp;
temp.c=cre[now.a][now.b-1].c;
temp.a=now.a;
temp.b=now.b-1;
temp.path=now.path+1;
temp.num=now.num;
if(cre[now.a][now.b-1].c=='A'||cre[now.a][now.b-1].c=='S')
{
temp.num=cre[now.a][now.b-1].num;
steps[begin][temp.num]=temp.path;
}
q.push(temp);
}
if(cre[now.a][now.b+1].c!='#'&&!visit[now.a][now.b+1])
{
visit[now.a][now.b+1]=1;
creature temp;
temp.c=cre[now.a][now.b+1].c;
temp.a=now.a;
temp.b=now.b+1;
temp.path=now.path+1;
temp.num=now.num;
if(cre[now.a][now.b+1].c=='A'||cre[now.a][now.b+1].c=='S')
{
temp.num=cre[now.a][now.b+1].num;
steps[begin][temp.num]=temp.path;
}
q.push(temp);
}
}
return;
}
int Prim(int v)//最小生成树算法
{
int i,j,mindis,minone;
int ans=0;
for(i=0;i<max_num;i++)
{
lowcost[i]=steps[v][i];
closest[i]=v;
}
for(i=1;i<max_num;i++)
{
mindis=INF;
for(j=0;j<max_num;j++)
if(lowcost[j]&&mindis>lowcost[j])
{
mindis=lowcost[j];
minone=j;
}
ans+=lowcost[minone];
lowcost[minone]=0;
for(j=0;j<max_num;j++)
{
if(steps[j][minone]<lowcost[j])
{
lowcost[j]=steps[j][minone];
closest[j]=minone;
}
}
}
return ans;
}
int main()
{
int n,x,y;
int i,j,minsteps;
creature start[cMAX];
char *s;
cin>>n;
while(n--)
{
cin>>x>>y;
s=new char[x+1];
k=0;
gets(s); //之前写了getchar(),测试结果一样,但是不能AC;改成gets(s),就A了。
//getc()是读取一行,而getchar()是读取一个字符
for(i=0;i<y;i++)
{
cin.getline(s,x+1,'\n');
for(j=0;j<x;j++)
{
cre[i][j].c=s[j];
cre[i][j].num=-1;
if(s[j]=='A')
{
start[k].a=i;
start[k].b=j;
start[k].num=k; //记录每个生物(A和S都是生物)的编号,为了后面steps[i][j]服务
start[k].c=s[j];
start[k].path=0;
cre[i][j].num=k;
k++;
}
if(s[j]=='S')
{
start[k].a=i;
start[k].b=j;
start[k].num=k;
start[k].c=s[j];
start[k].path=0;
cre[i][j].num=k;
s_start=k; //设置最小生成树的源点
k++;
}
}
}
for(i=0;i<k;i++) //对每个A和S执行BFS。一开始我想用一遍BFS就把它们相互之间的路径求出来,
//写了好久,发现根本不科学,每个执行一次就清晰多了。
{
memset(visit,0,sizeof(visit));
Pathcount_bfs(start[i]);
}
max_num=k;
minsteps=Prim(s_start);
cout<<minsteps<<endl;
}
delete []s;
return 0;
}