求凸包。
但是这题有个问题就是需要把在边界上的点也求出来,那么在判断cross的时候应该是<0 而不是 <=0。
还有一个问题是,排序的时候当极角相同的时候,按x从小到大的顺序排列的,那么最后几个共线的点顺序应该倒过来,不然结果只包含一个点。
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;
struct Point {
int x;
int y;
Point() : x(0), y(0) {}
Point(int a, int b) : x(a), y(b) {}
};
Point p0;
bool cmp(Point &a, Point &b) {
if ((a.x - p0.x) * ( b.y - p0.y) - ( a.y - p0.y) * ( b.x - p0.x) != 0) {
return (a.x - p0.x) * (b.y - p0.y) - (a.y - p0.y) * (b.x - p0.x) > 0;
}
else if (a.x != b.x){
return a.x < b.x;
}
else {
return a.y < b.y;
}
}
int cross(Point a, Point b, Point c) {
return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
}
void display(vector<Point> ans) {
cout << "---" << endl;
for (int i = 0; i < ans.size(); i++) {
cout << ans[i].x << " " << ans[i].y << endl;
}
cout << "---" << endl;
}
class Solution {
public:
vector<Point> outerTrees(vector<Point>& points) {
if (points.size() < 2) {
return points;
}
Point p(1e10, 1e10);
int min_index = 0;
for (int i = 0; i < points.size(); i++) {
if ((points[i].x <= p.x && points[i].y <= p.y) || points[i].x < p.x) {
min_index = i;
p = points[i];
}
}
p0 = p;
swap(points[0], points[min_index]);
sort(points.begin() + 1, points.end(), cmp);
int len = points.size();
if (cross(points[1], points[len - 1], points[0]) != 0) {
int temp = len - 2;
while (cross(points[len - 1], points[temp], points[0]) == 0) {
temp--;
}
reverse(points.begin() + temp + 1, points.end());
}
// display(points);
vector<Point> ans;
ans.push_back(points[0]);
ans.push_back(points[1]);
for (int i = 2; i < points.size(); i++) {
int t = ans.size();
while (ans.size() > 1 && cross(ans[t - 1], points[i], ans[t - 2]) < 0) {
ans.pop_back();
t = ans.size();
}
ans.push_back(points[i]);
}
return ans;
}
};
int main() {
Solution a;
vector<Point> points = {{3, 0}, {4, 0}, {5, 0}, {6, 1}, {7, 2}, {7, 3}, {7, 4}, {6, 5}, {5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 4}, {1, 3}, {1, 2}, {2, 1}};
vector<Point> ans = a.outerTrees(points);
for (int i = 0; i < ans.size(); i++) {
cout << ans[i].x << " " << ans[i].y << endl;
}
return 0;
}
/*
{{1, 1}, {2, 2}, {2, 0}, {2, 4}, {3, 3}, {4, 2}}
{{3, 0}, {4, 0}, {5, 0}, {6, 1}, {7, 2}, {7, 3}, {7, 4}, {6, 5}, {5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 4}, {1, 3}, {1, 2}, {2, 1}, {4, 2}, {0, 3}}
*/