http://acm.hdu.edu.cn/showproblem.php?pid=5251
集合叉积与点积的应用
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define N 10100
#define maxdouble 1e20
struct Point
{
double x, y;
bool operator < (const Point& other) const{
if (y != other.y)
return y < other.y;
return x < other.x;
}
};
struct TPolygon
{
int n;
Point p[N];
}ply;
double MIN(double a, double b) { return a>b ? b : a; }
double dist(Point a, Point b){//距离
return sqrt((b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y));
}
double cross(Point a, Point b, Point c){//叉积
return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
double dot(Point a, Point b, Point c){//点积
return (b.x - a.x)*(c.x - a.x) + (b.y - a.y)*(c.y - a.y);
}
bool cmp(Point a, Point b){return cross(ply.p[0], a, b)>0;}
int main()
{
int xp = 1;
int numx;
scanf("%d", &numx);
while (numx--){
scanf("%d", &ply.n);
int i;
double area;
ply.n *= 4;
for(i = 0; i<ply.n; i++) scanf("%lf%lf", &ply.p[i].x, &ply.p[i].y);
sort(ply.p, ply.p + ply.n);//排序
sort(ply.p + 1, ply.p + ply.n, cmp);
int j;
for(j = i = 2; i<ply.n; i++){
while (j>1 && cross(ply.p[j - 2], ply.p[i], ply.p[j - 1]) >= 0) j--;
ply.p[j++] = ply.p[i];
}
ply.n = j;
if (ply.n<3) area = 0;
else {
int top = 1, right = 1, left;
double minarea = maxdouble, _area;
ply.p[ply.n] = ply.p[0];
for(i = 0; i<ply.n; i++){
while (cross(ply.p[i], ply.p[i + 1], ply.p[top+ 1])//最上一点
- cross(ply.p[i], ply.p[i + 1], ply.p[top])>0)
top = (top + 1) % ply.n;
while (dot(ply.p[i], ply.p[i + 1], ply.p[right + 1])//最右一点
- dot(ply.p[i], ply.p[i + 1], ply.p[right]) > 0)
right = (right + 1) % ply.n;
if (i == 0) left= right;
while (dot(ply.p[i], ply.p[i + 1], ply.p[left+ 1])//最左一点
- dot(ply.p[i], ply.p[i + 1], ply.p[left]) <= 0)
left= (left+ 1) % ply.n;
double d = dist(ply.p[i], ply.p[i + 1])*dist(ply.p[i], ply.p[i + 1]);
_area = cross(ply.p[i], ply.p[i + 1], ply.p[top])*//求面积
(dot(ply.p[i], ply.p[i + 1], ply.p[right]) - dot(ply.p[i], ply.p[i + 1], ply.p[left])) / d;
minarea = MIN(_area, minarea);//更新
}
area = minarea;
}
printf("Case #%d:\n%.0lf\n", xp++, area);
}
return 0;
}