problem
Description
平面上有N颗树,标号从1到N,每颗树有坐标(Xi, Yi)。要求在平面上找几棵树,在一些树之间建篱笆形成一个闭合图形(篱笆不能在除了树以外的地方相交,形成的图形面积不能为0).求最小可能围成的面积。
Input
第一行输入N。
然后N行第i行输入第i棵树的坐标Xi和Yi。
Output
输出最小围成的面积,小数点后保留两位小数。无解输出“Impossible”
Sample Input
4
-1.00 0.00
0.00 -3.00
2.00 0.00
2.00 2.00
Sample Output
2.00
Data Constraint
对于40%数据 1 ≤ N ≤ 20
对于所有数据 1 ≤ N ≤ 100,-1000 ≤ Xi,Yi ≤ 1000
analysis
最优解的多边形一定是一个三角形
why?
首先如果在一个三角形外部有其他点,面积就会更大
在三角形内部有一个点,我们可以重新连接一个面积更小的三角形
海伦公式一搞,没了
code
注意精度!
c++的double精度过高,开方会出一个很小很小比0大一点点的小数,直接判断等于0是不行的
硬生生卡成WA80,hh……
#include<stdio.h>
#include<cmath>
#define MAXN 101
#define INF 1000000000000000000000000000000000000007.0
using namespace std;
double x[MAXN],y[MAXN];
int n;
double dis(int a,int b)
{
return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&x[i],&y[i]);
}
double ans=INF;
bool flag=0;
for (int i=1;i<=n;i++)
{
for (int j=i+1;j<=n;j++)
{
for (int k=j+1;k<=n;k++)
{
double p=(dis(i,j)+dis(i,k)+dis(j,k))/2;
double area=sqrt(p*(p-dis(i,j))*(p-dis(i,k))*(p-dis(j,k)));
if (dis(i,j)+dis(j,k)>dis(i,k) && dis(i,k)+dis(i,j)>dis(j,k) && dis(i,k)+dis(j,k)>dis(i,j))
if (area>0.01 && area<ans)
{
flag=1;
ans=area;
}
}
}
}
if (ans!=0 && flag)printf("%.2lf\n",ans);
else printf("Impossible\n");
return 0;
}