暴力枚举砍掉的树,然后对剩余的树求凸包
/**//*************************************************************************
Author: WHU_GCC
Created Time: 2007-8-11 13:56:20
File Name: pku1873.cpp
Description:
************************************************************************/
#include <iostream>
#include <cmath>
using namespace std;
#define out(x) (cout << #x << ": " << x << endl)
const int maxint = 0x7FFFFFFF;
typedef long long int64;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template <class T> void show(T a, int n) { for (int i = 0; i < n; ++i) cout << a[i] << ' '; cout << endl; }
template <class T> void show(T a, int r, int l) { for (int i = 0; i < r; ++i) show(a[i], l); cout << endl; }
const int maxn = 20;
typedef struct point_t
{
int x, y;
};
int operator <(const point_t &a, const point_t &b)
{
return a.y < b.y || a.y == b.y && a.x < b.x;
}
point_t operator -(const point_t &a, const point_t &b)
{
point_t ret;
ret.x = a.x - b.x;
ret.y = a.y - b.y;
return ret;
}
double dist(const point_t &a, const point_t &b)
{
return sqrt(double((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)));
}
int cross(const point_t &a, const point_t &b)
{
return a.x * b.y - a.y * b.x;
}
int turn_left(const point_t &a, const point_t &b, const point_t &c)
{
return cross(b - a, c - b) > 0;
}
typedef struct polygon_t
{
int n;
point_t p[maxn];
};
class point_set_c
{
public:
void init(int _n, point_t _p[]);
double convex_hull();
private:
int n;
point_t p[maxn];
};
void point_set_c::init(int _n, point_t _p[maxn])
{
n = _n;
for (int i = 0; i < n; i++)
p[i] = _p[i];
}
double point_set_c::convex_hull()
{
int stack[maxn];
int top = 1;
stack[0] = 0;
sort(p, p + n);
for (int i = 1; i < n;)
{
if (top == 1 || turn_left(p[stack[top - 2]], p[stack[top - 1]], p[i]))
stack[top++] = i++;
else top--;
}
int t_top = top;
for (int i = n - 2; i >= 0;)
{
if (top == t_top || turn_left(p[stack[top - 2]], p[stack[top - 1]], p[i]))
stack[top++] = i--;
else top--;
}
double ret = 0.0;
for (int i = 0; i < top - 1; i++)
ret += dist(p[stack[i]], p[stack[i + 1]]);
return ret;
}
int n;
point_t tree[maxn];
int v[maxn], l[maxn];
int ans_value, ans_num;
double ans_len;
int ans[maxn];
int used[maxn];
int dfs(int start)
{
if (start > n)
{
int tot_value = 0, tot_len = 0, tot_num = 0;
point_set_c ps;
point_t tmp[maxn];
int tt = 0;
for (int i = 0; i < n; i++)
if (used[i])
{
tot_value += v[i];
tot_len += l[i];
tot_num++;
}
else
tmp[tt++] = tree[i];
ps.init(tt, tmp);
double t = ps.convex_hull();
if (tot_len >= t)
{
if (tot_value < ans_value || tot_value == ans_value && tot_num < ans_num)
{
ans_value = tot_value;
ans_len = t;
ans_num = 0;
for (int i = 0; i < n; i++) if (used[i]) ans[ans_num++] = i;
}
}
}
for (int i = start; i <= n; i++)
if (!used[i])
{
used[i] = 1;
dfs(i + 1);
used[i] = 0;
}
}
int main()
{
int ca = 1;
while (scanf("%d", &n), n != 0)
{
for (int i = 0; i < n; i++)
scanf("%d%d%d%d", &tree[i].x, &tree[i].y, &v[i], &l[i]);
memset(used, 0, sizeof(used));
ans_value = maxint;
dfs(0);
printf("Forest %d\n", ca++);
printf("Cut these trees:");
for (int i = 0; i < ans_num; i++) printf(" %d", ans[i] + 1);
printf("\n");
double extra_wood = 0.0;
for (int i = 0; i < ans_num; i++) extra_wood += l[ans[i]];
extra_wood -= ans_len;
printf("Extra wood: %.2lf\n", extra_wood);
printf("\n");
}
return 0;
}
暴力枚举砍掉的树,然后对剩余的树求凸包