VJ 1069 新年趣事之红包

描述

xiaomengxian一进门,发现外公、外婆、叔叔、阿姨……都坐在客厅里等着 他呢。经过仔细观察,xiaomengxian发现他们所有人正好组成了一个凸多边形。最重要的是,他们每个人手里都拿着一个红包(^o^)。于是非常心 急,xiaomengxian决定找一条最短的路线,拿到所有的红包。

假设屋里共有N个人拿着红包,把他们分别从1到N编号。其中,编号为1的人就坐在大门口,xiaomengxian必须从这里出发去拿其它的红包。一条合法的路线必须经过所有的点一次且仅一次。

格式

输入格式

第一行为一个整数N(1<=N<=800)。

以下N行,每行两个实数Xi,Yi,表示该点的坐标。

各个点按照逆时针顺序依次给出。

输出格式

一个实数,表示最短的路线长度(保留三位小数)。

样例1

样例输入1[复制]

4
50.0 1.0
5.0 1.0
0.0 0.0
45.0 0.0

样例输出1[复制]

50.211

限制

各个测试点1s

 

题解:基本上都说是DP,但是因为我DP太弱。。根本不敢打,而且打了也不对。。于是就去写了克鲁斯卡尔求最小生成树,感觉并没有什么问题,欢迎各位大牛与我探讨

CODE:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define REP_(i, s, n) for(int i = n; i >= s; i --)
#define MAX_N 800 + 10

using namespace std;

int n, f[MAX_N];
double x[MAX_N], y[MAX_N];
struct node{
    int u, v;
    double w;
}E[700000];

bool cmp(node a, node b){ return a.w < b.w; }

int find(int x){
    if(f[x] == x) return x;
    return f[x] = find(f[x]);
}

int main(){
    scanf("%d", &n);
    int sum = 0;
    REP(i, 1, n) scanf("%lf%lf", &x[i], &y[i]);
    REP(i, 1, n) f[i] = i;
    REP(i, 1, n - 1) REP(j, i + 1, n){
        E[++ sum].u = i; E[sum].v = j;
        E[sum].w = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
    }
    
    double ans = 0;
    sort(E + 1, E + sum + 1, cmp);
    REP(i, 1, sum){
        int rx = find(E[i].u), ry = find(E[i].v);
        if(rx == ry) continue;
        f[ry] = rx;
        ans += E[i].w;
    }
    printf("%.3lf", ans);
    return 0;
}

 

posted @ 2015-05-24 19:02  ALXPCUN  阅读(300)  评论(0编辑  收藏  举报