Cod sursa(job #1118538)

Utilizator toranagahVlad Badelita toranagah Data 24 februarie 2014 11:50:02
Problema Popandai Scor 32
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.29 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 bseg[MAX_N][MAX_N];
int bpct[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 = 1; j <= N; j += 1) {
            if (j == i) continue;
            for (int k = 0; k <= N; 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));
                    int64_t area = get_area(i, j, k);

                    result = min(result, 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 = 1; k <= N; k += 1) {
                if (k == i || k == j) continue;
                if (p[k].x <= p[i].x || p[k].x >= p[j].x) continue;
                if (cross_product(p[i], p[j], p[k]) > 0) continue;

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

    for (int i = 1; i <= N; i += 1) {
        for (int j = 1; j <= N; j += 1) {
            if (i != j && p[i].x == p[j].x && p[j].y < p[i].y) {
                bpct[i] += 1;
            }
        }
    }
}

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

    int cp = cross_product(p[a], p[b], p[c]);
    if (cp < 0) {
        if (p[a].x == p[b].x) {
            return bseg[b][c] - bseg[a][c];
        } else {
            return bseg[a][b] + bseg[b][c] + bpct[b] - bseg[a][c];
        }
    } else {
        if (p[b].x == p[c].x) {
            return bseg[a][c] - bseg[a][b];
        } else {
            return bseg[a][c] - bseg[a][b] - bseg[b][c] - bpct[b] - 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);
}