Cod sursa(job #1175829)

Utilizator smaraldaSmaranda Dinu smaralda Data 24 aprilie 2014 23:44:39
Problema Popandai Scor 12
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.05 kb
#include<stdio.h>
#include<algorithm>
using namespace std;

const int NMAX = 300;
const double INF = 30000 * 30000;

int n, vert[NMAX + 5], trapez[NMAX + 5][NMAX + 5];
double best[NMAX + 5];

struct POINT {
    int x, y;
    POINT (int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }

    void read() {
        scanf("%d%d", &x, &y);
    }
};
POINT p[NMAX + 1];

int crossProduct (POINT P1, POINT P2, POINT P3) {
    return (P2.x - P1.x) * (P3.y - P2.y) - (P2.y - P1.y) * (P3.x - P2.x);
}

inline int abs (int x) {
    return x < 0 ? -x : x;
}

inline int dist (POINT a, POINT b) {
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

class cmp {
    public:
        bool operator () (POINT a, POINT b) {
            return a.x < b.x;
        }
};

inline int countPoints (int i, int j, int k) {
    if(dist(p[i], p[k]) > dist(p[i], p[j]))     //i-j cea mai lunga latura
        swap(j, k);
    if(dist(p[j], p[k]) > dist(p[i], p[j]))
        swap(i, k);

    if(crossProduct(p[i], p[j], p[k]) < 0)
        return trapez[i][k] + trapez[k][j] - trapez[i][j] - vert[k]; //k deasupra i-j
    return trapez[i][j] - trapez[i][k] - trapez[k][j] + vert[k] - 1; //k sub i-j
}

inline double area (POINT a, POINT b, POINT c) {
    return 0.5 * abs(crossProduct(a, b, c));
}

void getBest(int diag1, int diag2) {
    int i, ptsInTri;
    for(i = 0; i <= n; ++ i)
        best[i] = INF;

    for(i = 1; i <= n; ++ i)
        if(crossProduct(p[diag1], p[diag2], p[i]) > 0) {
            ptsInTri = countPoints(i, diag1, diag2);

            best[ptsInTri] = min(best[ptsInTri], area(p[i], p[diag1], p[diag2]));
        }

    for(i = n - 1; i >= 0; -- i)
        best[i] = min(best[i], best[i + 1]);
}

int main() {
    freopen("popandai.in", "r", stdin);
    freopen("popandai.out", "w", stdout);
    int  i, k, j, q, diag1, diag2, ptsInTri;
    double amin;

    scanf("%d%d", &n, &k);
    for(i = 1; i <= n; ++ i)
        p[i].read();

    sort(p + 1, p + 1 + n, cmp());

    for(i = 1; i <= n; ++ i)
        for(j = i + 1; j <= n; ++ j)
            for(q = 1; q <= n; ++ q)
                if(p[q].x >= p[i].x && p[q].x <= p[j].x && crossProduct(p[i], p[j], p[q]) < 0)
                    ++ trapez[i][j],
                    ++ trapez[j][i];

    for(i = 1; i <= n; ++ i)
        for(j = 1; j <= n; ++ j)
            if(p[j].x == p[i].x && p[j].y < p[i]. y)
                ++ vert[i];

    amin = INF;
    for(diag1 = 1; diag1 <= n; ++ diag1)
        for(diag2 = diag1 + 1; diag2 <= n; ++ diag2) {
            getBest(diag1, diag2);
            //best[i] = aria minima a unui triunghi cu vf in primul semiplan care contine cel putin i puncte

            for(i = 1; i <= n; ++ i)
                if(crossProduct(p[diag1], p[diag2], p[i]) < 0) {
                    ptsInTri = countPoints(diag1, diag2, i);

                    amin = min(amin, area(p[diag1], p[diag2], p[i]) + best[max(k - ptsInTri, 0)]);
                }
        }

    printf("%.1lf", amin);
    return 0;
}