题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3548
题意:
给定N个点的坐标求这些点能够成的周长最小的三角形的周长。
分析:
设三角形的三变长分别为,a,b,c; a<b+c;L=a+b+c;
因此当我们的当前的最小周长如果小于其中一条边的二倍的话
那么很明显有这个边构成的三角形的周长一定大于现在的周长,
我们可以根据这个性质进行减枝。
代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1010;
struct point{
double x,y;
bool operator < (const struct point &tmp)const{
return x<tmp.x;
}
}p[maxn];
inline double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline bool check(point a,point b,point c)
{
if((a.x-b.x)*(c.y-b.y)==(a.y-b.y)*(c.x-b.x))
return false;
return true;
}
int main()
{
int n,t,cas=1;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p,p+n);
bool f=0;
double ans = 1000000000;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ans <= 2*( p[j].x - p[i].x) )break;
double dd =dis(p[i],p[j]);
for(int k=j+1;k<n;k++){
if(ans<=2*(p[k].x-p[i].x)) break;
if(check(p[i],p[j],p[k])){
f=1;
if(ans>dis(p[i],p[k])+dis(p[j],p[k])+dd)
ans = dis(p[i],p[k])+dis(p[j],p[k])+dd;
}
}
}
}
if(f) printf("Case %d: %.3lf\n",cas++,ans);
else printf("Case %d: No Solution\n",cas++);
}
return 0;
}