南开 2216: Boring Game (排序)

Alice 和 Bob 是经常出现在一类叫“博奕问题”中的无聊玩家,因为他们很喜欢玩游戏,而这些游戏大都很无聊而且他们总会想让你帮忙判断输赢。出于某种神秘的原因你最好是能帮他们……

他们接下来要玩的一个无聊的游戏是这样的:一张纸上不知道谁画了 N (4 <= N < 1000)个点在上面,Alice 和 Bob 轮流在纸中各取一个点,Alice 先取。游戏一共进行两轮,结束后按照选取次序连接这四个点,并且最后一个点与第一个点相连,组成一个多边形,Alice 想让这个多边形的周长尽量小,而 Bob 这回竟然不和 Alice 唱反调了,他将帮助 Alice。他们将用最后得到的多边形做一个不为人知的事情(肯定也是很无聊的)。当然,以他们的能力,就算合作也无法解决这个问题,所以又要请你帮忙了。

Input

第一行一个整数N,接下来每行两个整数x, y (0 <= x, y < 100) 表示 N 个点。

Output

输出游戏结束后得到的多边形的周长(保留6位小数);如不存在这样的多边形,输出 -1。

Sample Input

5
0 0
2 0
2 1
1 2
0 1

Sample Output

6.000000

思路:枚举四个点必然超时。所以对每一个点找最近的三个点。对这四个点枚举所有可能的多边形。即枚举对角ab,ac,ad 即可。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <string>
#define LL long long
#define DB double
using namespace std;
int n;
struct cpoint{
    int x,y;
    void get(){scanf("%d%d",&x,&y);}
};
DB dist(cpoint a,cpoint b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+0.0);
}
DB ss(cpoint a,cpoint b,cpoint c,cpoint d)
{
    DB ans1 = dist(a,b)+dist(a,c)+dist(b,d)+dist(c,d);
    DB ans2 = dist(a,b)+dist(a,d)+dist(b,c)+dist(c,d);
    DB ans3 = dist(a,d)+dist(a,c)+dist(b,d)+dist(c,b);
    return min(ans1,min(ans2,ans3));
}
struct nod{
    int to;
    DB dis;
    bool operator<(const nod t)const
    {
        return dis<t.dis;
    }
};

struct nn{
    nod a[1009];
    void sove(){sort(a,a+n);}
} dis[1009];
cpoint re[1009];
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    scanf("%d",&n);
    for(int i=0;i<n;i++) re[i].get();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        dis[i].a[j].dis = dist(re[i],re[j]),dis[i].a[j].to=j;
        dis[i].sove();
    }
    DB ans = 1e20;
    for(int i=0;i<n;i++)
    {
        ans= min(ans,ss(re[dis[i].a[0].to],re[dis[i].a[1].to],re[dis[i].a[2].to],re[dis[i].a[3].to]));
    }printf("%.6lf\n",ans);
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值