poj3026 Borg Maze

 链接: http://poj.org/problem?id=3026 
题意: 有一个名叫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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值