There are some trees, where each tree is represented by (x,y) coordinate in a two-dimensional garden. Your job is to fence the entire garden using the minimum length of rope as it is expensive. The garden is well fenced only if all the trees are enclosed. Your task is to help find the coordinates of trees which are exactly located on the fence perimeter.
Copy Input: [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
Output: [[1,1],[2,0],[4,2],[3,3],[2,4]]
Explanation:
Copy Input: [[1,2],[2,2],[4,2]]
Output: [[1,2],[2,2],[4,2]]
Explanation:
Even you only have trees in a line, you need to use rope to enclose them.
Copy // 0: colinear
// > 0: counter-clockwise
// < 0: clockwise
int crossProduct(const vector<int>& A, const vector<int>& B, const vector<int>& C) {
int ABx = B[0] - A[0];
int ABy = B[1] - A[1];
int BCx = C[0] - B[0];
int BCy = C[1] - B[1];
return ABx * BCy - ABy * BCx;
}
int dist(const vector<int>& A, const vector<int>& B) {
return (B[0] - A[0]) * (B[0] - A[0]) + (B[1] - A[1]) * (B[1] - A[1]);
}
// Find the bottom left point as the starting point
int bottomLeftIdx(const vector<vector<int> >& points) {
int idx = 0;
for (int i = 1; i < points.size(); ++i) {
if (points[i][1] < points[idx][1] || (points[i][1] == points[idx][1] && points[i][0] < points[idx][0]))
idx = i;
}
return idx;
}
// Check if the colinear points are already in the result
bool check(const vector<vector<int> >& res, const vector<int>& p) {
for (const vector<int>& r : res) {
if (r[0] == p[0] && r[1] == p[1]) return false;
}
return true;
}
vector<vector<int>> outerTrees(vector<vector<int>>& points) {
int n = points.size();
vector<vector<int> > res;
res.reserve(n);
int firstIdx = bottomLeftIdx(points);
const vector<int>& first = points[firstIdx];
res.push_back(first);
int curIdx = firstIdx;
vector<int> cur = points[curIdx];
while (true) {
vector<int> nex = points[0];
int nexIdx = 0;
for (int i = 1; i < n; ++i) {
if (i == curIdx) continue;
int cross = crossProduct(cur, points[i], nex);
if (nexIdx == curIdx || cross > 0 || (cross == 0 && dist(points[i], cur) > dist(nex, cur) ) ) {
nex = points[i];
nexIdx = i;
}
}
for (int i = 0; i < n; ++i) {
if (i == curIdx) continue;
int cross = crossProduct(cur, points[i], nex);
if (cross == 0) {
if (check(res, points[i])) res.push_back(points[i]);
}
}
cur = nex;
curIdx = nexIdx;
if (curIdx == firstIdx) break;
}
res.resize(res.size());
return res;
}