题意:给你四个点,四个人在四个点上舞动丝带,各条丝带不能相遇,求四人最大的丝带总长度。
思路:可以分为三种情况讨论.
1是四个点在一条线上,择取两端的线段和为最大值,因为中间的部分为重复计算的,且中间两个点的半径可以无穷小.一定可以放下两个圆.
2是四个点构成一个四边形,这种情况容易证得至少有两对圆是相切的,这种情况下选择任意两条对边,和小的那对为最大值.其实总共有6条边两条对角线肯定是可以舍弃。如果所选两条对边是第一,二短的那么显然正确(此种情况是每两个圆相切)。(下面几种情况可以归为4个圆分别在所选两对边和比这两对边小的边上两两相切)如果是第2,3短的那么假设以这两条边的顶点为圆心的圆是在这两条边上是相切的同时让其中两圆在第1短的边上相切,如此显然成立。对边为其他情况的依次类推。
3是取三个点构成一个三角形,第四个点在三角形内部,这种情况可以去掉对角线之和,因为题目中给定的点的顺序是一定的.这种和第2种相似。
综上所述,只需去任意两条边,使得这两条边包含所有的点,所有满足条件的组合中最小的一组即为最大值。
以上大部分摘自http://blog.csdn.net/freezhanacmore/article/details/9392363
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct Point{
double x;
double y;
}p[5];
double dist(Point a, Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
int main()
{
while(scanf("%lf%lf", &p[0].x, &p[0].y) != EOF)
{
for(int i = 1; i < 4; i++)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
}
double d1 = dist(p[0], p[1]);
double d2 = dist(p[1], p[2]);
double d3 = dist(p[2], p[3]);
double d4 = dist(p[0], p[3]);
double d5 = dist(p[0], p[2]);
double d6 = dist(p[1], p[3]);
double ans = min(d1+d3, min(d4+d2, d5+d6));
printf("%.8lf\n", ans);
}
return 0;
}
//这是大神的代码
#include <iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct dian
{
double x,y;
};
struct chang
{
double l;
int st,en;
};
int main()
{
dian d[6];
while(cin>>d[0].x>>d[0].y)
{ int i;
for(i=1;i<4;++i)
cin>>d[i].x>>d[i].y;
chang cc[20];int ci=0;
for(i=0;i<4;++i)
{
for(int j=i+1;j<4;j++)
{
cc[ci].l=sqrt((d[j].x-d[i].x)*(d[j].x-d[i].x)+(d[j].y-d[i].y)*(d[j].y-d[i].y) );
cc[ci].st=i;cc[ci].en=j;
++ci;
}
}
printf("%.8lf\n",min((cc[0].l+cc[5].l),min(cc[1].l+cc[4].l,cc[2].l+cc[3].l)));
}
return 0;
}
//这是我在自己错误代码上改的ac代码。