Simple convex hull + brute force enumeration.
/* Geometric Convex Hull + brute force */# include <algorithm> # include <iostream> # include <string. h> # include <stdlib. h> # include <stdio. h> # include <math. h >#include <queue> # include <stack> # include <map> # include <set> using namespace std; typedef long int64; // typedef _ int64 int64; typedef pair <int64, int64> PII; # define MP (a, B) make_pair (a), (B) const int inf = 0x3f3f3f3f; const double pi = acos (-1.0); const int dx [] = {1,-, 0}; const int dy [] = {0, 0, 1,-1}; const double eps = 1e-8; const int maxm = 1005; const int maxn = 16; struct Point2 {int x, y; double val, len; bool OK; // OK = vertices to be removed} pnt [maxn]; int cur [maxn]; int cnt_cur; double val_cur, ans1; int best [maxn]; int cnt_best; double val_best, ans2; double Len1, Len2; struct Point {double x, y; bool operator <(const Point & t) const {return y <t. y | (y = t. y & x <t. x) ;}} a [maxn], res [maxn]; double Xmult (Point sp, Point ep, Point op) {return (sp. x-op.x) * (ep. y-op.y)-(sp. y-op.y) * (ep. x-op.x);} double dist (int I, int j) {return sqrt (res [I]. x-res [j]. x) * (res [I]. x-res [j]. x) + (res [I]. y-res [j]. y) * (res [I]. y-res [j]. y);} int Graham (int n) {int top = 1; sort (a, a + n); if (n = 0) return 0; else res [0] = a [0]; if (n = 1) return 1; else res [1] = a [1]; if (n = 2) return 2; else res [2] = a [2]; for (int I = 2; I <n; I ++) {While (top> 0 & xmult (res [top], res [top-1], a [I])> = 0) top --; res [+ top] = a [I];} int len = top; res [+ top] = a [N-2]; for (int I = n-3; i> = 0; I --) {while (top! = Len & xmult (res [top], res [top-1], a [I])> = 0) top --; res [++ top] = a [I];} return top;} bool Solve (int n) {double temp1 = 0; int cc = 0; for (int I = 0; I <n; I ++) {if (pnt [I]. OK = false) {a [cc]. x = 1.0 * pnt [I]. x; a [cc]. y = 1.0 * pnt [I]. y; cc ++;} else temp1 + = pnt [I]. len;} int q = cc; cc = Graham (q); double temp2 = 0; res [cc] = res [0]; for (int I = 0; I <cc; I ++) {temp2 + = dist (I, I + 1);} ans1 = temp2; L En1 = temp1; if (temp2 <= temp1) return true; else return false;} int main () {int n; int Case = 1; while (scanf ("% d", & n), n) {if (Case! = 1) printf ("\ n"); for (int I = 0; I <n; I ++) {scanf ("% d % lf ", & pnt [I]. x, & pnt [I]. y, & pnt [I]. val, & pnt [I]. len);} int N = (1 <n); ans1 = ans2 = 0; val_best = 9999999999.0; for (int I = 0; I <N; I ++) {cnt_cur = 0; val_cur = 0; for (int j = 0; j <n; j ++) {if (I & (1 <j )) {cur [cnt_cur ++] = j; pnt [j]. OK = true; val_cur + = pnt [j]. val;} elsepnt [j]. OK = false;} if (cnt_cur = n) continue; if (Solve (n) = true) {// printf ("Solve \ n "); if (val_cur <val_best) {val_best = val_cur; for (int k = 0; k <cnt_cur; k ++) {best [k] = cur [k];} cnt_best = cnt_cur; ans2 = ans1; Len2 = Len1;} else if (val_cur = val_best) {if (cnt_cur <cnt_best) {for (int k = 0; k <cnt_cur; k ++) {best [k] = cur [k];} cnt_best = cnt_cur; ans2 = ans1; Len2 = Len1 ;}}}} printf ("Forest % d \ n", Case ++); printf ("Cut these trees:"); for (int I = 0; I <cnt_best; I ++) printf ("% d", best [I] + 1); printf ("\ n"); printf ("Extra wood: %. 2lf \ n ", Len2-ans2);} return 0 ;}