Freckles - 九度 OJ 1144

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LYKXHTP/article/details/88601146

Freckles - 九度 OJ 1144

题目

时间限制:1 秒 内存限制:128 兆 特殊判题:否
题目描述:
In an episode of the Dick Van Dyke show, little Richie connects the freckles on his Dad’s back to form a picture of the Liberty Bell. Alas, one of the freckles turns out to be a scar, so his Ripley’s engagement falls through.Consider Dick’s back to be a plane with freckles at various (x,y) locations. Your job is to tell Richie how to connect the dots so as to minimize the amount of ink used. Richie connects the dots by drawing straight lines between pairs, possibly lifting the pen between lines. When Richie is done there must be a sequence of connected lines from any freckle to any other freckle.
输入:
The first line contains 0 < n <= 100, the number of freckles on Dick’s back. For each freckle, a line follows; each following line contains two real numbers indicating the (x,y) coordinates of the freckle.
输出:
Your program prints a single real number to two decimal places: the minimum total length of ink lines that can connect all the freckles.
样例输入:
3
1.0 1.0
2.0 2.0
2.0 4.0
样例输出:
3.41
来源:
2009年北京大学计算机研究生机试真题

题目大意为平面上有若干个点,需要用一些线段来将这些点连接起来使任意两个点能够通过一系列的线段相连,给出所有点的坐标,求一种连接方式使所有线段的长度和最小,求该长度和。
若将平面上的点抽象成图上的结点,将结点间直接相邻的线段抽象成连接结点的边,且权值为其长度,那么该类似于几何最优值的问题就被转化到了图论上的最小生成树问题。但在开始求最小生成树前,必须先建立该图, 得出所有的边和相应的权值。

#include <stdio.h>
#include <math.h>
#include <algorithm>
#define N 101

using namespace std;

int Tree[N];

int findRoot(int x){
    if(Tree[x]==-1)return x;
    else{
        int tmp=findRoot(Tree[x]);
        Tree[x]=tmp;
        return tmp;
    }
}

struct Edge{
    int a,b;
    double cost;//权值变为长度,改用浮点数
    bool operator < (const Edge &A) const{
        return cost < A.cost;
    }
}edge[6000];

struct Point{//点结构体
    double x,y;//点的两个坐标值
    double getDistance(Point A){
        //计算点之间的距离
        double tmp=(x-A.x)*(x-A.x)+(y-A.y)*(y-A.y);
        return sqrt(tmp);
    }
}list[101];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&list[i].x,&list[i].y);
        }
        int size=0;//抽象出的边的总数
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                //连接两点的线段抽象成边
                edge[size].a=i;
                edge[size].b=j;//该边的两个顶点编号
                edge[size].cost=list[i].getDistance(list[j]);
                //边权值为两点之间的长度
                size++;//边的综述增加
            }//遍历所有的点对
        }
        sort(edge,edge+size);//对边按权值递增排序
        for(int i=1;i<=n;i++){
            Tree[i]=-1;
        }
        double ans=0;
        for(int i=0;i<size;i++){
            int a=findRoot(edge[i].a);
            int b=findRoot(edge[i].b);
            if(a!=b){
                Tree[a]=b;
                ans+=edge[i].cost;
            }
        }//最小生成树
        printf("%.2lf\n",ans);
    }
    return 0;
}

最小生成树算法除了 Kruskal 算法,还有其他一些算法,比较有名的还有 Prim 算法。但两者在机试题上应用时差别不大,所以这里不再讨论 Prim算法。

猜你喜欢

转载自blog.csdn.net/LYKXHTP/article/details/88601146
今日推荐