poj3026Borg Maze_最小生成树(广搜+prim算法)

题目链接!


题很简单,就是求最小生成树的,难点就在于将图转化成边(带权值),就是这一块不好转化。

我想到了用广搜去找每个顶点到其他顶点的距离,但是在代码实现上有些困难,参考了别人的代码后就恍然大悟了,

觉得在prim算法上会很简单,但是同样也遇到了问题,就是在dis[]初始值时候,不知道初始谁了。总认为要先将S(开始搜索的地方)加入第一个dis值中,这样的一个错误的想法就卡住了。

看来还是没有深刻的理解最小生成树含义,从任何一个顶点出发都能到达各个顶点的最小价值。所以S和A的意义是一样的。

还有在进入广搜的时候,我也没有理解透彻!(最后和这个代码从下午死磕到晚上,最后还是别人

给我调试出来的。。。。别人要求我加入他的链接

在广搜之前就要把求得各个顶点到顶点的最小距离d[]进行初始化,因为每次搜索的是传入的顶点到其它各个顶点的最小距离。


#include<stdio.h>
#include<queue>
#include<string.h>
#define max 1<<31-1
using namespace std;

char map[55][55];
int num_map[55][55];
int vis[55][55];
int time[55][55];
int d[55][55];
int dis[110];
int book[110];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

int n,m,num;
struct node{
	int u;
	int v;
	node(int uu,int vv):u(uu),v(vv){
	}
	node(){
	}
}no[110];
void bfs(node nd)
{
	memset(time,0,sizeof(time));
    memset(vis,0,sizeof(vis));
  
	
	int i,j;
	
	
	      
	queue<node>Q;
	Q.push(nd);
	vis[nd.u][nd.v]=1;
	
	while(!Q.empty())
	{
		
		node n1=Q.front();
		Q.pop();
		
		for(i=0;i<4;i++)
		{
			int x=n1.u+dx[i];
			int y=n1.v+dy[i];
			if(x>=0&&x<n&&y>=0&&y<m&&vis[x][y]!=1&&map[x][y]!='#')
			{
				time[x][y]=time[n1.u][n1.v]+1;
				vis[x][y]=1;
				Q.push(node(x,y));
				if(num_map[x][y]>0)
				{
					d[num_map[nd.u][nd.v]][num_map[x][y]]=time[x][y];
				}
			}
		}
	}
}
int prim()
{

	memset(book,0,sizeof(book));
	
	int i,j,count=0,sum=0;
	
	for(i=1;i<=num;i++)
	  dis[i]=max;
	  
	dis[1]=0;
	while(count<num)
	{
		int min=max;
		for(i=1;i<=num;i++)
		{
			if(!book[i]&&dis[i]<min)
			{
				j=i;
				min=dis[i];
			}
		}
		
		book[j]=1;
		count++;
	
		sum+=dis[j];
		
		for(i=1;i<=num;i++)
		{
			if(!book[i]&&dis[i]>d[j][i])
			{
			
				 dis[i]=d[j][i];
			}
			  
		}
	
	}
	
	return sum;
}
int main()
{
	int T,i,j;
	scanf("%d",&T);
	while(T--)
	{
		memset(num_map,0,sizeof(num_map));
		scanf("%d%d",&m,&n);
		char str[110];
		gets(str);
		for(i=0;i<n;i++)
		   gets(map[i]);
		num=0;
	
		for(i=0;i<n;i++)
		  for(j=0;j<m;j++)
		  {
		  	if(map[i][j]=='S'||map[i][j]=='A')
		  	{
		  		num_map[i][j]=++num;
		  	}
		  }
		for(i=1;i<=num;i++)
	  for(j=1;j<=num;j++)
	      d[i][j]=max;
	      
	  for(i=0;i<n;i++)
	     for(j=0;j<m;j++)
	     	if(num_map[i][j]>0)
	     	  	bfs(node(i,j));
				
	     		     	    
	   printf("%d\n",prim());  
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值