暴力枚举,求凸包即可,不用特判,因为算法本身在一颗树的时候凸包长度就是0.
枚举用递归实现,从砍1颗~砍n-1颗一次枚举,所以不用判断在最小值相同时选砍数最少的情况(因为本来就是从砍1颗开始算的)
代码如下,思路挺清晰的。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct Node
{
double x, y,
v, l;
}v[16], p[16];
int n, ans[16], nown, ansn, stack[16];
bool vst[16];
double extra, minv;
bool cmp(Node a, Node b)
{
if (a.y ==
b.y)
return a.x < b.x;
return
a.y < b.y;
}
double multi(Node a, Node b, Node c, Node d)
{
b.x -=
a.x;
b.y -=
a.y;
d.x -=
c.x;
d.y -=
c.y;
return b.x *
d.y - d.x * b.y;
}
bool turn_left(Node a, Node b, Node c)
{
return
multi(a, b, b, c) > 0;
}
double dist(Node a, Node b)
{
return
sqrt(1.0 *(a.x - b.x) * (a.x - b.x) (a.y - b.y) * (a.y -
b.y));
}
double Judge()
{
int top =
1;
stack[0] =
0;
sort(p, p
nown, cmp);
for (int i =
1; i < nown;)
{
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 =
nown - 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;
}
void dg(int deep, int num, double val, double len, int from)
{
if (deep ==
num)
{
if (val > minv)
return;
int temp = 0;
for(int k = 0; k < n; k )
if (!vst[k])
p[temp ] = v[k];
double dis = Judge();
if (len >= dis)
{
if (val < minv)
{