Cod sursa(job #3295515)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 6 mai 2025 12:18:10
Problema Triangulare Scor 0
Compilator cpp-64 Status done
Runda Arhiva ICPC Marime 2.77 kb
// Unibuc Reds
#include<bits/stdc++.h>
using ll=long long;
constexpr int NMAX=64;
constexpr ll MOD=1000000007;

struct pct{
	int x, y;
};

struct Segment{
	pct a, b;
};

int f(pct a, pct b, pct c){
	return a.x * b.y + a.y * c.x + b.x * c.y - b.y * c.x - a.x * c.y - a.y * b.x;
}

bool bounding_boxes(Segment A, Segment B){
	using namespace std;
	if(max(A.a.x, A.b.x) < min(B.a.x, B.b.x) || max(B.a.x, B.b.x) < min(A.a.x, A.b.x)) return false;
	if(max(A.a.y, A.b.y) < min(B.a.y, B.b.y) || max(B.a.y, B.b.y) < min(A.a.y, A.b.y)) return false;
	return true;
}

bool check(Segment s, Segment t)
{
	return ( bounding_boxes(s, t) && f(s.a, s.b, t.a) * (ll)f(s.a, s.b, t.b) <= 0 &&
		f(t.a, t.b, s.a) * (ll)f(t.a, t.b, s.b) <= 0);
}

int N;
pct v[NMAX];
std::bitset<NMAX> cantDo[NMAX];
typedef std::pair<int, int> sg;
std::vector<sg> sol;

void divide(std::vector<int> a)
{
	if(a.size()<4u)
		return;

	int i, j, k;
	for(i=0;i<(int)a.size();++i)
		for(j=i+1;j<(int)a.size();++j)
			if(!cantDo[a[i]][a[j]])
			{
				std::vector<int> l, r;
				for(k=0;k<=i;++k)
					l.push_back(a[k]);
				for(k=i;k<=j;++k)
					r.push_back(a[k]);
				for(k=j;k<(int)a.size();++k)
					l.push_back(a[k]);
				if(l.size()>2u && r.size()>2u)
				{
					sol.push_back({a[i], a[j]});
					cantDo[a[i]][a[j]]=1;
					return divide(l), divide(r);
				}
			}

	fprintf(stderr, "Error\n");
	// while(1);
}

int sgn(double x)
{
	return (x>0)-(x<0);
}

bool inside(double x, double y)
{
	int i, j, cnt=0;

	for(i=0;i<N;++i)
	{
		j=(i+1)%N;
		if(y>std::max(v[i].y, v[j].y) || y<=std::min(v[i].y, v[j].y))
			continue;
		if(x>std::max(v[i].x, v[j].x))
			continue;
		if(x<=std::min(v[i].x, v[j].x))
			++cnt;
		else
		{
			int mx=std::min(v[i].x, v[j].x), my=std::min(v[i].y, v[j].y);
			if((mx==v[i].x && my==v[i].y) || (mx==v[j].x && my==v[j].y))
				my=std::max(v[i].y, v[j].y);
			if(
			sgn(v[i].x * v[j].y + v[i].y * mx + v[j].x * my - v[j].y * mx - v[i].x * my - v[i].y * v[j].x)*
			sgn(v[i].x * v[j].y + v[i].y * x + v[j].x * y - v[j].y * x - v[i].x * y - v[i].y * v[j].x)>=0
			) ++cnt;
		}
	}

	return cnt%2;
}

void solve()
{
	int i, j, k;

	scanf("%d", &N);
	for(i=0;i<N;++i)
		scanf("%d%d", &v[i].x, &v[i].y);

	for(i=0;i<N;++i)
		for(j=i+2, cantDo[i].reset();j<N;++j)
		{
			for(k=0;k<N;++k)
				if(k!=i && k!=j && k!=(i+N-1)%N && k!=j-1 && check({v[i], v[j]}, {v[k], v[(k+1)%N]}))
					cantDo[i][j]=1;
			if(!inside(0.5*(v[i].x+v[j].x), 0.5*(v[i].y+v[j].y)))
				cantDo[i][j]=1;
		}
	for(i=0;i<N;++i)
	{
		if(f(v[i], v[(i+1)%N], v[(i+2)%N])==0)
			cantDo[i][(i+2)%N]=1;
		cantDo[i][(i+1)%N]=1;
	}

	std::vector<int> a;
	for(i=0;i<N;++i)
		a.push_back(i);
	divide(a);

	std::sort(sol.begin(), sol.end());

	for(sg s : sol)
		printf("%d %d\n", s.first, s.second);
	sol.clear();
}

int main()
{
	int _=1;

	scanf("%d", &_);
	do solve(); while(--_);

	return 0;
}