HDU 3548 Enumerate the Triangles(找周长最小的三角形+优化)

【题目链接】:Click here~~

【题意】:平面上有n(n<=1000)点,问组成的三角形中,周长最小是多少。

【解题思路】:此题有个优化点,首先考虑直接枚举的话,是O(n^3)肯定会超时,所以要优化。接着我们考虑,判断组成三角形的条件和特殊情况,周长C=L1+L2+L3,有C> 2Li,假设Li的两端分别为点a、b,则又有Li>=| Xa-Xb |,故C> 2*| Xa-Xb |。所以先按照X坐标从小到大排序,然后当已得到的最小值area<= 2*|Xa-Xb|的时候,就跳出循环。

代码:

/*
* Problem: HDU No.3548
* Running time: 93MS
* Complier: G++
* Author: javaherongwei
* Create Time: 15:29 2015/10/4 星期日
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;

#define min(a,b) a<b?a:b

const int maxn=1e3+10;
const double eps=1e-8;
int n;

struct tag
{
    int x,y;
    bool operator <(const tag& a) const
    {
        return x<a.x;
    }
} s[maxn];

double dis(const tag& a,const tag& b) ///两点之间距离
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

bool one_line(const tag& a,const tag&b,const tag& c) ///特判三点共线
{
    return (b.y-a.y)*(c.x-b.x)==(c.y-b.y)*(b.x-a.x);
}

bool ok(tag a,tag b,tag c)/// 判断能否组成三角形
{
    double len_ab=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    double len_ac=sqrt((a.x-c.x)*(a.x-c.x)+(a.y-c.y)*(a.y-c.y));
    double len_cb=sqrt((c.x-b.x)*(c.x-b.x)+(c.y-b.y)*(c.y-b.y));
    if(len_ab+len_ac>len_cb&&len_ab+len_cb>len_ac&&len_ac+len_cb>len_ab) return true;
    return false;
}

inline LL read(){
    int  c=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    return c*f;
}
int main()
{
    int t,tot=1;t=read();
    while(t--)
    {
        n=read();
        for(int i=0; i<n; ++i)
            s[i].x=read(),s[i].y=read();
        sort(s,s+n);
        double area=1e7;
        for(int i=0; i<n-2; ++i)
        {
            for(int j=i+1; j<n-1; ++j)
            {
                 if(area<=2*abs(s[j].x-s[i].x)) break;
                 double a=dis(s[i],s[j]);
                 if(area<=2*a) continue;
                 for(int k=j+1; k<n; ++k)
                 {
                     if(area<=2*abs(s[k].x-s[i].x)) break;
                     if(one_line(s[i],s[j],s[k])||!ok(s[i],s[j],s[k])) continue;
                     double b=dis(s[j],s[k]);
                     double c=dis(s[k],s[i]);
                     area=min(area,a+b+c);
                 }
            }
        }
        printf("Case %d: ",tot++);
        if(area==1e7) puts("No Solution");
        else printf("%.3f\n",area);
    }
    return 0;
}

/*
Sample Input
2
3
0 0
1 1
2 2
4
0 0
0 2
2 1
1 1

Sample Output
Case 1: No Solution
Case 2: 4.650
*/


你可能感兴趣的:(HDU,计算几何,三角形周长)