n最大15,二进制枚举不会超时。枚举不被砍掉的树,然后求凸包
#include
#include
#include
#include
#include
#define eps 1e-8
#define INF 1e9
using namespace std;
const int MAXN = 20;
struct Point
{
int x,y;
int v,l;
};
Point pot[MAXN];
int stck[MAXN],top;
int sgn(double x)
{
if(fabs(x) < eps) return 0;
return x < 0 ? -1:1;
}
int cross(Point p0,Point p1,Point p2) //计算叉积 p0p1 X p0p2
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
double dis(Point p1,Point p2) //计算 p1p2的 距离
{
return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
bool cmp(Point p1,Point p2) //极角排序函数,角度相同则距离小的在前面
{
int tmp=cross(pot[0],p1,p2);
if(tmp>0) return true;
else if(tmp==0&&dis(pot[0],p1)<dis(pot[0],p2)) return true;
else return false;
}
void init(int n) //输入,并把最左下方的点放在 pot[0]。并且进行极角排序
{
int i,k;
Point p0;
p0 = pot[0];
k=0;
for(i=1; i
{
p0 = pot[i];
k=i;
}
}
pot[k]=pot[0];
pot[0]=p0;
sort(pot+1,pot+n,cmp);
}
void graham(int n)
{
int i;
if(n==1)
{
top=0;
stck[0]=0;
}
if(n==2)
{
top=1;
stck[0]=0;
stck[1]=1;
}
if(n>2)
{
for(i=0; i<=1; i++) stck[i]=i;
top=1;
for(i=2; i<n; i++)
{
while(top>0&&cross(pot\[stck\[top-1\]\],pot\[stck\[top\]\],pot\[i\])<=0) top--;
top++;
stck\[top\]=i;
}
}
}
Point p[MAXN];
int main()
{
// freopen("in.txt","r",stdin);
int n, val, len, minv, maxn, ans;
double exc;
int Case = 0;
while(~scanf("%d", &n) && n)
{
val = len = 0;
for(int i=0; i
}
init(cnt);
graham(cnt);
double d = 0;
for(int j=0; j<=top; j++)
d += dis(pot[stck[j]], pot[stck[(j+1)%(top+1)]]);
if(sgn(l - d) >= 0)
{
if(v < minv || (v == minv && cnt > maxn))
{
minv = v;
maxn = cnt;
ans = i;
exc = l - d;
}
}
}
printf("Forest %d\nCut these trees: ", ++Case);
for(int i=0; i
}
printf("\nExtra wood: %.2lf\n\n", exc);
}
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章