Cod sursa(job #2113180)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 24 ianuarie 2018 12:27:24
Problema Popandai Scor 28
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.92 kb
/**
  *  Worg
  */
#include <cstdio>
#include <vector>
#include <algorithm>

#define x first
#define y second

typedef std::pair<double, double > Point;

FILE *fin = freopen("popandai.in", "r", stdin); FILE *fout = freopen("popandai.out", "w", stdout);

const double kMaxInf = 1e17;
const double eps = 1e-8;

/*-------- Data --------*/
int n, k;
std::vector<Point > pts;

std::vector<std::vector<int > > under;

double sol = kMaxInf;
/*-------- --------*/

void ReadInput() {
  scanf("%d%d", &n, &k);
  for(int i = 0; i < n; i++) {
    double a, b; scanf("%lf%lf", &a, &b); pts.emplace_back(a, b);
  }
}

double CrossProduct(Point A, Point B, Point C) {
  return (B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y);
}

void ComputeDp() {
  //  under[i][j] = how many points are under the [i, j] segment
  under = std::vector<std::vector<int > >(n, std::vector<int >(n, 0));

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

  for(int i = 0; i < n; i++) {
    for(int j = i + 1; j < n; j++) {
      for(int act = 0; act < n; act++) {
        if(CrossProduct(pts[i], pts[j], pts[act]) < -eps && pts[i].x <= pts[act].x && pts[act].x <= pts[j].x) {
          under[i][j]++;
        }
      }
    }
  }
}

double Area(Point A, Point B, Point C) {
  return 0.5 * std::fabs(A.x * B.y + B.x * C.y + C.x * A.y - B.x * A.y - A.x * C.y - C.x * B.y);
}

void Solve() {
  std::vector<double > up, down;

  for(int i = 0; i < n; i++) {
    for(int j = i + 1; j < n; j++) {
      up = down = std::vector<double >(k + 1, kMaxInf);

      //  Check all triangles
      for(int act = 0; act < n; act++) {
        if(act == i || act == j) continue;
        int here;

        if(CrossProduct(pts[i], pts[j], pts[act]) > 0) {  //  up
          if(pts[act].x < pts[i].x) {
            here = under[act][j] - under[act][i] - under[i][j];
          } else if(pts[act].x > pts[j].x) {
            here = under[i][act] - under[i][j] - under[j][act];
          } else {
            here = under[i][act] + under[act][j] - under[i][j];
          }

          if(here > k) here = k;

          up[here] = std::min(up[here], Area(pts[i], pts[j], pts[act]));
        } else {  //  down
          if(pts[act].x < pts[i].x) {
            here = under[act][i] + under[i][j] - under[act][j];
          } else if(pts[act].x > pts[j].x) {
            here = under[i][j] + under[j][act] - under[i][act];
          } else {
            here = under[i][j] - under[i][act] - under[act][j];
          }

          if(here > k) here = k;

          down[here] = std::min(down[here], Area(pts[i], pts[j], pts[act]));
        }
      }

      //  Update solution
      double dp = kMaxInf;
      for(int here = 0; here <= k; here++) {
        dp = std::min(dp, down[k - here]);
        sol = std::min(sol, up[here] + dp);
      }
    }
  }
}

int main() {
  ReadInput();

  ComputeDp();

  Solve();

  printf("%.1f\n", sol);
	return 0;
}