Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cstdlib>
- #include <cassert>
- #include <ctime>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- #include <vector>
- #include <string>
- #include <queue>
- #include <set>
- #include <map>
- using namespace std;
- #define pb push_back
- #define mp make_pair
- #ifdef DEBUG
- #define eprintf(...) fprintf(stderr, __VA_ARGS__)
- #define TIMESTAMP(msg) eprintf("[ " #msg " ] Time=%.3lfs\n", clock() * 1.0 / CLOCKS_PER_SEC)
- #else
- #define eprintf(...)
- #define TIMESTAMP(msg)
- #endif
- #define sz(x) ((int)(x).size())
- #define TASKNAME "convexset"
- typedef long long ll;
- typedef long double ld;
- typedef vector<ll> vll;
- typedef vector<int> vi;
- typedef vector<vi> vvi;
- typedef vector<bool> vb;
- typedef vector<vb> vvb;
- typedef pair<int, int> pii;
- typedef pair<ll, int> pli;
- const int INF = 1e9;
- const int inf = INF;
- const double EPS = 1e-9;
- const double eps = EPS;
- int sgn(int x) { return x < 0 ? -1 : !!x; }
- struct pt {
- int x, y, id;
- pt() : x(0), y(0), id(-1) {}
- pt(int x, int y) : x(x), y(y), id(-1) {}
- double dist() const { return sqrt(x * x + y * y); }
- pt operator-(const pt &p2) const { return pt(x - p2.x, y - p2.y); }
- int operator*(const pt &p2) const { return sgn(x * p2.y - y * p2.x); }
- bool operator<(const pt &p2) const { return y != p2.y ? y < p2.y : x < p2.x; }
- };
- bool rcmp(const pt &a, const pt &b) {
- return a * b > 0;
- }
- bool isang(const pt &b, const pt &c, const pt &p) {
- return b * p > 0 && p * c > 0;
- }
- bool check_inside(pt a, pt b, pt c, pt p) {
- b = b - a; c = c - a; p = p - a; a = pt();
- if (b * c < 0) swap(b, c);
- assert(b * c > 0);
- if (!isang(b, c, p)) return false;
- if (!isang(c - b, pt() - b, p - b)) return false;
- return true;
- }
- const int MAXN = 60;
- vi inside[MAXN][MAXN][MAXN];
- const vi& getIn(int a, int b, int c) {
- if (a > b) swap(a, b);
- if (b > c) swap(b, c);
- if (a > b) swap(a, b);
- return inside[a][b][c];
- }
- double dist[MAXN][MAXN];
- int k;
- pair<double, int> dyn[MAXN + 1][MAXN + 2];
- pair<double, vi> solve(vector<pt> &pts) {
- int n = sz(pts);
- pts.pb(pts[0]);
- for (int i = 0; i <= n; i++)
- for (int j = 0; j <= n + 1; j++)
- dyn[i][j] = mp(1e100, -1);
- dyn[0][0] = mp(0, -1);
- for (int pr = 0; pr < n; pr++)
- for (int pcnt = 0; pcnt <= n; pcnt++) if (dyn[pr][pcnt].first < 1e99) {
- double cur = dyn[pr][pcnt].first;
- for (int ne = pr + 1; ne <= n; ne++) {
- int ncnt = pcnt + 1 + sz(getIn(pts[0].id, pts[pr].id, pts[ne].id));
- assert(ncnt <= n);
- dyn[ne][ncnt] = min(dyn[ne][ncnt], mp(cur + dist[pts[pr].id][pts[ne].id], pr));
- }
- }
- double bres = dyn[n][k].first;
- for (int i = k + 1; i <= n; i++)
- assert(dyn[n][i].first >= bres - eps);
- vi res;
- int pcnt = k;
- for (int ne = n; ne > 0;) {
- int pr = dyn[ne][pcnt].second;
- assert(pr >= 0);
- const vi &in = getIn(pts[0].id, pts[pr].id, pts[ne].id);
- pcnt -= 1 + sz(in);
- res.insert(res.end(), in.begin(), in.end());
- res.pb(pts[ne].id);
- ne = pr;
- }
- assert(pcnt == 0);
- // eprintf("%d == %d\n", sz(res), k);
- assert(sz(res) == k);
- return mp(bres, res);
- }
- int main() {
- freopen(TASKNAME ".in", "r", stdin);
- freopen(TASKNAME ".out", "w", stdout);
- int n;
- while (scanf("%d%d", &n, &k) == 2) {
- vector<pt> pts(n);
- for (int i = 0; i < n; i++)
- scanf("%d%d", &pts[i].x, &pts[i].y), pts[i].id = i;
- for (int i = 0; i < n; i++)
- for (int j = 0; j < n; j++)
- dist[i][j] = (pts[i] - pts[j]).dist();
- for (int i = 0; i < n; i++)
- for (int j = i + 1; j < n; j++)
- for (int k = j + 1; k < n; k++) {
- for (int x = 0; x < n; x++) if (x != i && x != j && x != k && check_inside(pts[i], pts[j], pts[k], pts[x])) {
- inside[i][j][k].pb(x);
- }
- }
- pair<double, vi> bans;
- bans.first = 1e100;
- for (int bot = 0; bot < n; bot++) {
- vector<pt> rem;
- for (int i = 0; i < n; i++)
- if (pts[bot] < pts[i]) {
- pt res = pts[i] - pts[bot];
- assert(pt() < res);
- res.id = i;
- rem.pb(res);
- }
- sort(rem.begin(), rem.end(), rcmp);
- pt root; root.id = bot;
- rem.insert(rem.begin(), root);
- if (sz(rem) >= k) {
- pair<double, vi> cans = solve(rem);
- bans = min(bans, cans);
- }
- }
- assert(sz(bans.second) == k);
- printf("%.18lf\n", bans.first);
- for (int i = 0; i < sz(bans.second); i++)
- printf("%d%c", bans.second[i] + 1, "\n "[i + 1 < sz(bans.second)]);
- for (int i = 0; i < n; i++)
- for (int j = i + 1; j < n; j++)
- for (int k = j + 1; k < n; k++)
- inside[i][j][k].clear();
- }
- TIMESTAMP(end);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement