Cod sursa(job #341849)

Utilizator savimSerban Andrei Stan savim Data 19 august 2009 18:47:23
Problema Popandai Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.17 kb
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>

using namespace std;

#define MAX_N 310
#define inf 2147000000
                        
int n, k;
int prec[MAX_N][MAX_N];
int sus[MAX_N], smin[MAX_N], jos[MAX_N], jmin[MAX_N];
struct punct {
	int x;    
	int y;
} V[MAX_N];
int sol = inf;

inline int cmp(punct P, punct Q) {
	if (P.x != Q.x) return P.x < Q.x;
	else return P.y < Q.y;
}

inline int cmp2(int i, int j) {
	if (V[i].x != V[j].x) {
    	if (V[i].x < V[j].x) return 0;
		else return 1;
	}
	else {
    	if (V[i].y < V[j].y) return 0;
		else return 1;
	}
}

void cit() {
	freopen("popandai.in", "r", stdin);
	freopen("popandai.out", "w", stdout);

	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++)
		scanf("%d %d", &V[i].x, &V[i].y);
	sort(V + 1, V + n + 1, cmp);
}

double tang(punct P, punct Q) {
	if (P.x != Q.x) return 1.0 * (Q.y - P.y) / (Q.x - P.x);
	else {
    	if (Q.y < P.y) return -inf;
		else return inf;
	}
}

void precalculare() {
	for (int i = 1; i <= n - 1; i++)
    	for (int j = i + 1; j <= n; j++) {
			if (V[j].x != V[i].x)
			for (int k = i - 1; k < j; k++)
				if (k) {
					if (k > i && tang(V[i], V[k]) < tang(V[i], V[j]))
						prec[i][j]++;
					if (k == i - 1 && V[k].x == V[i].x) prec[i][j]++;
				}
			prec[j][i] = prec[i][j];
		}
}

int det (int i, int j, int k) {
	return V[i].x * V[j].y + V[j].x * V[k].y + V[k].x * V[i].y - 
		   V[i].y * V[j].x - V[j].y * V[k].x - V[k].y * V[i].x;
}

int sup(int i, int j, int k) {
	return abs(V[i].x * V[j].y + V[j].x * V[k].y + V[k].x * V[i].y -
               V[i].y * V[j].x - V[j].y * V[k].x - V[k].y * V[i].x);
}

int nr_punct(int i, int j, int k) {
	//trebuie sa sortez punctele i, j, k
	if (cmp2(i, j)) swap(i, j);
	if (cmp2(i, k)) swap(i, k);
	if (cmp2(k, j)) swap(k, j);

	int ret = 0;
	if (V[i].x != V[j].x && V[j].x != V[k].x) {
		int gas = 0;
		if (V[j - 1].x == V[j].x) gas = 1;

		if (det(i, j, k) < 0) {
			ret = prec[i][j] + prec[j][k] - prec[i][k];
			if (gas) ret--;
		}
		else {
			ret = prec[i][k] - prec[i][j] - prec[j][k] - 1;
			if (gas) ret++;
		}
	}
	else {
    	if (V[i].x == V[j].x)
			ret = prec[j][k] - prec[i][k] - 1;
		else
			ret = prec[i][k] - prec[i][j] - 1;
	}

	return ret;
}

void solve() {
	precalculare();

	for (int i = 1; i < n; i++)
		for (int j = i + 1; j <= n; j++) {
			sus[0] = jos[0] = 0;
			for (int t = 1; t <= n; t++) {
				if (t != i && t != j) {
                	if (det(i, j, t) > 0) sus[++sus[0]] = t;
					else jos[++jos[0]] = t;
				}
			}
		    for (int t = 0; t <= k; t++)
				smin[t] = jmin[t] = inf;
		
			for (int t = 1; t <= sus[0]; t++) {
				int arie = sup(i, j, sus[t]), nr = nr_punct(i, j, sus[t]);
				if (arie < smin[nr])
					smin[nr] = arie;
			}

			for (int t = 1; t <= jos[0]; t++) {
            	int arie = sup(i, j, jos[t]), nr = nr_punct(i, j, jos[t]);
				if (arie < jmin[nr])
					jmin[nr] = arie;
			}                      
			for (int t = k - 1; t >= 0; t--)
				jmin[t] = min(jmin[t], jmin[t + 1]);
                                                              
			for (int t = 0; t <= k; t++)
				if (smin[t] != inf && jmin[k - t] != inf)
					sol = min(sol, smin[t] + jmin[k - t]);   
		} 

	printf("%.1lf\n", 1.0 * sol / 2);
}

int main() {

	cit();
	solve();

	return 0;
}