Skip to content

Instantly share code, notes, and snippets.

@Icaro-Lima
Last active March 3, 2018 15:22
Show Gist options
  • Select an option

  • Save Icaro-Lima/7f99a19deefe158505c6aa2f9131c567 to your computer and use it in GitHub Desktop.

Select an option

Save Icaro-Lima/7f99a19deefe158505c6aa2f9131c567 to your computer and use it in GitHub Desktop.
#include <bits/stdc++.h>
using namespace std;
struct Vector {
int x, y;
Vector() : x(0), y(0) { }
Vector(int x, int y) : x(x), y(y) { }
int outer(Vector other) {
return x * other.y - y * other.x;
}
double mod() {
return sqrtf(x * x + y * y);
}
};
struct Point {
int x, y;
Point(int x, int y) : x(x), y(y) { }
Point() : x(0), y(0) { }
Vector operator -(Point other) {
return Vector(x - other.x, y - other.y);
}
bool operator ==(Point other) {
return x == other.x && y == other.y;
}
string str() {
return "(" + to_string(x) + " " + to_string(y) + ")";
}
};
Point pre_selected;
bool comp(Point a, Point b) {
if (a == pre_selected) {
return true;
} else if (b == pre_selected) {
return false;
}
Vector aa = a - pre_selected, bb = b - pre_selected;
int outer = aa.outer(bb);
if (outer > 0) {
return true;
} else if (outer < 0) {
return false;
} else {
return aa.mod() < bb.mod();
}
}
bool is_collinear(Point a, Point b, Point c) {
return (b - a).outer(c - b) == 0;
}
void remove_layer(vector<Point> &points) {
int min_left = 0;
for (int i = 1; i < points.size(); i++) {
if (points[i].x < points[min_left].x) {
min_left = i;
} else if (points[i].x == points[min_left].x) {
if (points[i].y < points[min_left].y) {
min_left = i;
}
}
}
pre_selected = points[min_left];
sort(points.begin(), points.end(), comp);
vector<Point> layer_points;
layer_points.push_back(points[0]);
layer_points.push_back(points[1]);
for (int i = 2; i < points.size(); i++) {
Vector base = layer_points.back() - layer_points[layer_points.size() - 2];
Vector new_vector = points[i] - layer_points.back();
while (layer_points.size() > 2 && base.outer(new_vector) < 0) {
layer_points.pop_back();
new_vector = points[i] - layer_points.back();
base = layer_points.back() - layer_points[layer_points.size() - 2];
}
layer_points.push_back(points[i]);
}
Vector base = layer_points.back() - layer_points[layer_points.size() - 2];
Vector new_vector = layer_points.front() - layer_points.back();
while (layer_points.size() > 2 && base.outer(new_vector) < 0) {
layer_points.pop_back();
new_vector = layer_points.front() - layer_points.back();
base = layer_points.back() - layer_points[layer_points.size() - 2];
}
for (int i = layer_points.size() - 1; i >= 0; i--) {
vector<Point>::iterator it = find(points.begin(), points.end(), layer_points[i]);
points.erase(it);
}
for (int i = 0; i < points.size(); i++) {
for (int j = 0; j < layer_points.size() - 1; j++) {
if (is_collinear(layer_points[j], points[i], layer_points[j + 1])) {
points.erase(points.begin() + i);
i--;
continue;
}
}
if (is_collinear(layer_points[layer_points.size() - 1], points[i], layer_points[0])) {
points.erase(points.begin() + i);
i--;
}
}
}
int main() {
int n;
while (scanf("%d", &n) && n != 0) {
vector<Point> points;
for (int i = 0; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
points.push_back(Point(x, y));
}
int count = 0;
while (points.size() >= 3) {
remove_layer(points);
count++;
}
printf(count % 2 != 0 ? "Take this onion to the lab!\n" : "Do not take this onion to the lab!\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment