题目链接:点击打开链接
题目的意思很简单,就是求一个凸包。Graham_scan扫描法求解凸包。第一次写凸包,搞的头大。各种。这是还是没有任何的精度判断。还有另外一种,算法也可以求解。先学这个再说,以后再说精度的判断。
code:代码写的各种残,希望以后会有很好转吧。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1e2 + 5;
struct Point{
double x, y;
}p[N];
struct Vector{
double x, y;
};
double operator *(Vector A, Vector B){
return A.x * B.y - A.y * B.x;
}
Vector operator -(Point a, Point b){// vector ab
Vector tmp;
tmp.x = b.x - a.x; tmp.y = b.y - a.y;
return tmp;
}
double Distance(Point a, Point b){
return sqrt( pow(a.x - b.x, 2.0) + pow(a.y - b.y, 2.0));
}
bool cmp(Point a, Point b){
if(a.y < b.y) return true;
else if(a.y == b.y && a.x < b.x) return true;
return false;
}
bool cmp1(Point a, Point b){//点按逆时针排序.
Vector A, B;
A.x = a.x - p[0].x; A.y = a.y - p[0].y;
B.x = b.x - p[0].x; B.y = b.y - p[0].y;
if(A * B < 0) return false;
else if(A * B == 0 && Distance(a, p[0]) < Distance(b, p[0])) return false;
else return true;
}
bool cmp2(Point a, Point b){
if(a.x < b.x || (a.x == b.x && a.y < b.y)) return true;
return false;
}
Point st[N];//手动模逆栈效果更好.
int top;
bool Judge(Point a, Point b, Point c){
// printf("%.0lf %.0lf %.0lf %.0lf %.0lf %.0lf\n",a.x, a.y, b.x, b.y, c.x, c.y);
Vector A, B;
A = a - b; B = c - b;
// printf(" Judge = %.3lf\n", A * B);
if(A * B < 0 ) return true;
else return false;
}
void Braham_scan(int n){
if(n < 3) return; //小于三个点的时候,不存在凸包.
sort(p, p + n, cmp); //找到基点.
sort(p + 1, p + n, cmp1);//按极角进行排序.sort的内部实现.!
top = 0;
st[top ++] = p[0]; st[top ++] = p[1];
for(int i = 2; i < n; i ++){
// printf("%.1lf %.1lf\n",p[i].x, p[i].y);
while(Judge(st[top - 1], st[top - 2], p[i]) && top >= 2){
top --;
}
st[top ++] = p[i];
}
sort(st, st + top, cmp2);
for(int i = 0; i < top; i ++){
printf("%.0lf %.0lf\n", st[i].x, st[i].y);
}
}
int main(){
// freopen("1.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T --){
int n;
scanf("%d", &n);
for(int i = 0; i < n; i ++){
scanf("%lf %lf", &p[i].x , &p[i].y);
}
Braham_scan(n);
}
return 0;
}
多练习一下,还要去学最近点对,最远点对,旋转卡壳......