Cod sursa(job #1118702)

Utilizator toranagahVlad Badelita toranagah Data 24 februarie 2014 12:48:20
Problema Popandai Scor 32
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.76 kb
#include <cstdint>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

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

typedef pair<int, int> Point;
#define x first
#define y second
#define mp make_pair

const int MAX_N = 305;
const int64_t INF = 1LL << 60;

int N, K;
Point p[MAX_N];
int below[MAX_N][MAX_N];
int64_t x[MAX_N];

void comp_below();
int cross_product(const Point &O, const Point &A, const Point &B);
int64_t get_area(int a, int b, int c);
int get_inside(int a, int b, int c);

int main() {
    fin >> N >> K;
    for (int i = 1; i <= N; i += 1) {
        fin >> p[i].x >> p[i].y;
    }
    comp_below();

    int64_t result = INF;
    for (int i = 1; i <= N; i += 1) {
        for (int j = i + 1; j <= N; j += 1) {
            if (j == i) continue;
            for (int k = 0; k <= N + 1; k += 1) x[k] = INF;

            for (int k = 1; k <= N; k += 1) {
                if (k == j || k == i) continue;
                if (cross_product(p[i], p[j], p[k]) < 0) {
                    int inside = get_inside(i, j, k);
                    int64_t area = get_area(i, j, k);

                    x[inside] = min(x[inside], area);
                }
            }

            for (int k = N; k > 0; k -= 1) {
                x[k - 1] = min(x[k - 1], x[k]);
            }

            for (int k = 1; k <= N; k += 1) {
                if (k == j || k == i) continue;
                if (cross_product(p[i], p[j], p[k]) > 0) {
                    int needed = max(0, K - get_inside(i, j, k));
                    if (x[needed] == INF) continue;
                    int area = get_area(i, j, k);

                    result = min(result, 1LL * area + x[needed]);
                }
            }

        }
    }
    fout << (1.0 * result) / 2.0;

    return 0;
}

inline int cross_product(const Point &O, const Point &A, const Point &B) {
    return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}

void comp_below() {
    sort(p + 1, p + N + 1);
    for (int i = 1; i <= N; i += 1) {
        for (int j = i + 1; j <= N; j += 1) {
            for (int k = i + 1; k < j; k += 1) {
                if (cross_product(p[i], p[j], p[k]) > 0) continue;

                below[i][j] += 1;
                below[j][i] += 1;
            }
        }
    }
}

inline int get_inside(int a, int b, int c) {
    if (p[b] < p[a]) swap(a, b);
    if (p[c] < p[a]) swap(a, c);
    if (p[c] < p[b]) swap(b, c);

    if (cross_product(p[a], p[b], p[c]) < 0) {
        return below[a][b] + below[b][c] - below[a][c];
    }
    return below[a][c] - below[a][b] - below[b][c] - 1;
}

inline int64_t get_area(int a, int b, int c) {
    return abs(1LL * p[a].x * p[b].y + p[b].x * p[c].y + p[c].x * p[a].y -
               p[c].x * p[b].y - p[b].x * p[a].y - p[a].x * p[c].y);
}