POJ 1873 The Fortified Forest 二进制枚举 + 凸包 (final水题)
RT,注意考虑凸包点数小于3的情况
View Code
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; #define eps 1e-8 #define inf 1<<29 struct point { int x, y; point(){} point(int xx, int yy) : x(xx), y(yy){} }; struct data { int x, y, v, l; }d[16]; int det(int x1, int y1, int x2, int y2) { return x1 * y2 - x2 * y1; } int cross(point o, point a, point b) { return det(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } double f(int x) { return x * x * 1.0; } double dis(point a, point b) { return sqrt( f(a.x - b.x) + f(a.y - b.y) ); } int min_v, min_n; int n, m; bool vis[17]; int con[17]; bool cmp(point a, point b) //水平序 { if(a.y == b.y) return a.x < b.x; return a.y < b.y; } double graham(point p[], int n, int len) //返回剩余的长度 { if(n == 0 || n == 1) return len * 1.000; if(n == 2) return len * 1.000 - 2 * dis(p[0], p[1]); int i; sort(p, p + n, cmp); int top = 0; point res[17]; for(i = 0; i < n; i++) { while(top >= 2 && cross(res[top-2], res[top-1], p[i]) < 0) top--; res[top++] = p[i]; } int t = top + 1; for(i = n - 2; i >= 0; i--) { while(top >= t && cross(res[top-2], res[top-1], p[i]) < 0) top--; res[top++] = p[i]; } double ans = 0; for(i = 0; i < top - 1; i++) ans += dis(res[i], res[i+1]); return len * 1.000 - ans; } int main() { int i, j, ca = 1; int val, num, tree, len, x; //损失的价值val, 没砍掉的树的个数num,砍掉的树的个数tree //砍掉一些树所能用的长度len, 最小砍掉树的个数x double rest; // 剩余量rest point pp[17]; while ( ~scanf("%d", &n) && n) { for(i = 0; i < n; i++) scanf("%d%d%d%d", &d[i].x, &d[i].y, &d[i].v, &d[i].l); min_n = n+1; min_v = inf; rest = 0; for(i = 0; i < (1<<n); i++) { len = val = num = tree = 0; for(j = 0; j < n; j++) { vis[j] = 0; if( i & (1<<j)) { val += d[j].v; len += d[j].l; tree++; vis[j] = 1; } else pp[num++] = point(d[j].x, d[j].y); } if(val > min_v || ( val == min_v && min_n <= tree) )continue; if(len == 0 && num != 1) continue; double ans = graham(pp, num, len); if(ans >= 0) { min_v = val; min_n = tree; rest = ans; x = 0; for(j = 0; j < n; j++) if(vis[j]) con[x++] = j; } } printf("Forest %d\nCut these trees:", ca++); for(j = 0; j < x; j++) printf(" %d", con[j]+1); printf("\nExtra wood: %.2f\n\n", rest); } return 0; }