http://poj.org/problem?id=3348
题意:用树围城一块地, 求最大的面积。
思路:凸包加多边形面积
点集排序(0ms):
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10015;
struct Point{
int x, y;
friend bool operator < (Point a, Point b){
return a.y < b.y || (a.y == b.y && a.x < b.x);
}
};
//叉积
double mult(Point a, Point b, Point c){
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
int graham(int n, Point *point, Point *res)
{
sort(point, point+n); //点集排序
if(n == 0) return 0; res[0] = point[0];
if(n == 1) return 1; res[1] = point[1];
if(n == 2) return 2; res[2] = point[2];
int top = 1;
//求半个凸包
for(int i = 2; i < n; i++){
while(top && mult(point[i], res[top], res[top-1]) >= 0){
top--;
}
res[++top] = point[i];
}
//另外半个凸包
int len = top;
for(int i = n-2; i >= 0; i--){
while(top > len && mult(point[i], res[top], res[top-1]) >= 0){
top--;
}
res[++top] = point[i];
}
return top;
}
//多边形面积
double Area(int n, Point *res)
{
double sum = 0.0;
if(n < 3) return sum;
for(int i = 0; i < n; i++){
sum += mult(res[0], res[i], res[(i+1)%n]); //叉积求面积
}
return sum / 2.0;
}
Point res[maxn];
Point point[maxn];
int main()
{
int n;
while(~scanf("%d", &n)){
for(int i = 0; i < n; i++){
scanf("%d%d", &point[i].x, &point[i].y);
}
int top = graham(n, point, res);
double sum = Area(top, res) / 50;
printf("%d\n",(int)abs(sum));
}
return 0;
}
极角排序(16ms):
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10015;
const double eps = 1e-8;
struct Point{
double x, y;
friend bool operator < (Point a, Point b){
return a.y < b.y || (a.y == b.y && a.x < b.x);
}
};
Point res[maxn];
Point point[maxn];
//周长
double length(Point a, Point b){
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
//叉积
double mult(Point a, Point b, Point c){
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
//求面积
double Area(int n, Point *res)
{
double sum = 0.0;
if(n < 2) return sum;
for(int i = 1; i < n; i++){
sum += fabs(mult(res[0], res[i], res[i+1])); //叉积的绝对值就是构成的三角形面积的两倍
}
return sum / 2.0;
}
//极角排序
bool cmp(Point a, Point b)
{
int k = mult(point[0], a, b);
return k > 0 || (k == 0 && length(point[0], a) < length(point[0], b));
}
int graham(int n, Point *point, Point *res)
{
sort(point, point+n, cmp); //极角排序
if(n == 0) return 0; res[0] = point[0];
if(n == 1) return 1; res[1] = point[1];
if(n == 2) return 2; res[2] = point[2];
int top = 1;
for(int i = 2; i < n; i++){
while(top && mult(point[i], res[top], res[top-1]) >= 0){
top--;
}
res[++top] = point[i];
}
return top;
}
int main()
{
int n;
while(~scanf("%d", &n)){
int tx = 100000, ty = 100000, mid;
for(int i = 0; i < n; i++){
scanf("%lf%lf", &point[i].x, &point[i].y);
if(point[i].y < ty || (point[i].y == ty && point[i].x < tx)){
mid = i;
tx = point[i].x;
ty = point[i].y;
}
}
point[mid] = point[0]; // 极角排序要求point[0]是最左下角的点
point[0].x = tx, point[0].y = ty;
int top = graham(n, point, res);
double sum = Area(top, res) / 50;
printf("%d\n",(int)sum);
}
return 0;
}