判定有问题,一旦将n==2的注释部分解除注释就出错(明明计算过程一样)
#include <bits/stdc++.h>
#define maxn 160
using namespace std;
struct Point
{
int x, y;
};
Point p[maxn], ch[maxn]; //后者记录凸包上的点
bool cmp(Point x, Point y)
{
return x.x < y.x || (x.x == y.x && x.y < y.y); //x从小到大排序,如果x相同则y从小到大排序
}
int Cross(Point x, Point y, Point z)
{
int x1 = x.x - y.x;
int y1 = x.y - y.y;
int x2 = z.x - y.x;
int y2 = z.y - y.y;
if ((x1 * y2 - x2 * y1) <= 0)
return 0; //如果不希望在凸包的边上有输入点。把<=改成<
//小于等于0说明yx在yz左侧,符合凸包
return 1;
}
double dis(Point a, Point b)
{
return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int andrew(int n)
{
sort(p, p + n, cmp);
int m = 0;
int i;
for (i = 0; i < n; i++) //从左到右扫描
{
while (m > 1 && !Cross(ch[m - 1], ch[m - 2], p[i]))
m--;
ch[m++] = p[i];
}
int k = m;
for (i = n - 2; i >= 0; i--) //从右到左扫描
{
while (m > k && !Cross(ch[m - 1], ch[m - 2], p[i]))
m--;
ch[m++] = p[i];
}
if (n > 1)
m--; //凸包有m个顶点
return m;
}
int main()
{
int n;
while (~scanf("%d", &n) && n)
{
for (int i = 0; i < n; i++)
scanf("%d %d", &p[i].x, &p[i].y);
if (n == 1)
{
printf("0.00\n");
continue;
}
// if (n == 2)
// {
// printf("%.2lf\n", dis(ch[0], ch[1]));
// continue;
// }
int m = andrew(n);
double ans = 0;
for (int i = 0; i < m; i++) //计算绳长
{
if (i == m - 1)
ans += dis(ch[i], ch[0]);
else
ans += dis(ch[i], ch[i + 1]);
}
if (n == 2)
ans /= 2.0;
printf("%.2lf\n", ans);
}
// system("pause");
return 0;
}