蓝桥杯模拟赛c++实现村子规划费用问题

21 篇文章 0 订阅
12 篇文章 0 订阅

最小生成树问题

先来了解一下最小生成树

在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得
的 w(T) 最小,则此 T 为 G 的最小生成树。

其实就是来计算最小权的算法,本文用prim算法实现

for (i = 2; i <= n; i++) 
 { 
 min = MAXCOST; 
 minid = 0; 
 for (j = 2; j <= n; j++) 
 { 
 if (lowcost[j] < min && lowcost[j] != 0) 
 { 
 min = lowcost[j];//找出权值最短的路径长度 
 minid = j; //找出最小的ID 
 } 
 } 
 printf("V%d-V%d=%d\n",mst[minid],minid,min); 
 sum += min;//求和 
 
 lowcost[minid] = 0;//该处最短路径置为0 
 for (j = 2; j <= n; j++)
 { 
 if (graph[minid][j] < lowcost[j])//对这一点直达的顶点进行路径更新 
 { 
 lowcost[j] = graph[minid][j]; 
 mst[j] = minid;
 } 
 } 
 } 
 printf("最小权值之和=%d\n",sum);
}

现在是不是发现,蓝桥这道题目
完完全全就是典型的最小生成树问题:

#include<iostream>
#include<cmath>
using namespace std;
struct cc{//村庄 
	int x;
	int y;
	int h;
};
//所有变量,必须初始化!!!!
double fy(cc x,cc y){//费用 
	 double z=sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y))+(x.h-y.h)*(x.h-y.h);
	 return z;
}
int main(){
	int n;
	cin>>n;
	cc *a=new cc[n];
	for(int i=0;i<n;i++){
		cin>>a[i].x>>a[i].y>>a[i].h;
	}
    double **b=new double*[n];
    for(int i=0;i<n;i++){
    	b[i]=new double[2];
    	b[i][1]=0;//没有联通
		b[i][0]=10000;
	}
	b[0][0]=0;//距离最小设为0 
	b[0][1]=1;//1号建发电站,已连接 
    for(int i=1;i<n;i++){
    	b[i][0]=fy(a[0],a[i]);
	}
//	for(int i=0;i<n;i++)
//	    cout<<b[i][0]<<" "<<b[i][1]<<endl;
    int temp=1;
    double sum=0;
    double min;
    int min_i;
    while(temp<n){
    	min=100000;
    	for(int i=1;i<n;i++){//寻找没有联通的村庄里联通的最小费用 
    		if(b[i][1]==0){
    			if(min>b[i][0]){
    				min=b[i][0];
    				min_i=i;
				}
			}
		}
		b[min_i][1]=1;//划为联通的村庄 
		sum+=b[min_i][0];//划归联通的村庄的费用
		for(int i=1;i<n;i++){
          if(b[i][1]==0){//没有联通的村庄重新计算联通最小费用
          	if(b[i][0]>fy(a[min_i],a[i]))
          	   b[i][0]=fy(a[min_i],a[i]);
		  }
	    }
	    temp++;//权值统计
	} 
	printf("%.2f",sum);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值