Cod sursa(job #2003384)

Utilizator iordache.bogdanIordache Ioan-Bogdan iordache.bogdan Data 22 iulie 2017 20:07:51
Problema Triangulare Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 2.95 kb
#include <bits/stdc++.h>
using namespace std;

const int kMaxN = 55;
const double kEps = 1e-7;
typedef pair<double, double> Point;
typedef pair<Point, Point> Segment;

ifstream fin("triangulare.in");
ofstream fout("triangulare.out");

int N;
vector< Point > polygon, triangulation;

bool IsZero(const double& x) {
	return fabs(x) < kEps;
}

double Determinant(const Point& a, const Point& b, const Point& c) {
	return (b.first - a.first)*(c.second - a.second) - (b.second - a.second)*(c.first - a.first);
}

bool IsInsidePolygon(const Point& p) {
	Point q(1000000, rand() % 1000000);

	bool isInside = false;
	for (int i = 0; i < N; ++i) {
		int j = (i + 1) % N;

		if (Determinant(p, polygon[i], polygon[j])*Determinant(q, polygon[i], polygon[j]) > 0
			&& Determinant(polygon[i], p, q)*Determinant(polygon[j], p, q) < -kEps)
			isInside ^= true;
	}

	return isInside;
}

bool IntersectIntervals(double left1, double right1, double left2, double right2) {
	if (left1 > left2) {
		swap(left1, left2);
		swap(right1, right2);
	}

	return right1 - left2 > kEps;
}

bool IntersectSegments(const Segment& a, const Segment& b) {
	if (IsZero(Determinant(a.first, a.second, b.first)) && IsZero(Determinant(a.first, a.second, b.second))) {
		if (IntersectIntervals( min(a.first.first, a.second.first), max(a.first.first, a.second.first),
								min(b.first.first, b.second.first), max(b.first.first, b.second.first) )
			|| IntersectIntervals( min(a.first.second, a.second.second), max(a.first.second, a.second.second),
								   min(b.first.second, b.second.second), max(b.first.second, b.second.second) ))
			return true;
		else
			return false;
	}

	return (Determinant(a.first, a.second, b.first)*Determinant(a.first, a.second, b.second) < -kEps
			&& Determinant(b.first, b.second, a.first)*Determinant(b.first, b.second, a.second) < -kEps);
}

bool CheckCut(Segment cutSegment) {
	for (int i = 0; i < N; ++i) {
		if (IntersectSegments(cutSegment, Segment(polygon[i], polygon[(i + 1) % N])))
			return false;
	}

	for (auto& it : triangulation) {
		if (IntersectSegments(cutSegment, Segment(polygon[it.first], polygon[it.second])))
			return false;
	}

	return IsInsidePolygon(Point( (cutSegment.first.first + cutSegment.second.first)/2,
								  (cutSegment.first.second+ cutSegment.second.second)/2 ));
}

int main() {
	srand(time(NULL));

	int testCount;
	fin >> testCount;

	while (testCount--) {
		fin >> N;
		polygon.resize(N);

		for (auto& it : polygon)
			fin >> it.first >> it.second;

		triangulation.clear();
		for (int i = 0; i < N; ++i) {
			for (int j = (i + 2) % N; (j + 1) % N != i; j = (j + 1) % N) {
				if (CheckCut(Segment(polygon[i], polygon[j])))
					triangulation.push_back({ min(i, j), max(i, j) });
			}
		}

		sort(triangulation.begin(), triangulation.end());
		for (auto it : triangulation)
			fout << it.first << ' ' << it.second << '\n';
	}

	return 0;
}

//Trust me, I'm the Doctor!