题目链接:
http://poj.org/problem?id=1873
题解:
学会了一个新的枚举方法。。二进制枚举。。然后凸包搞一搞就好了
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
struct node
{
int x,y,v;
double l;
}e[20], tubao[20];
vector<node> retree;
double templen;
int tempvalue,tempi;
bool cmp(node a, node b)
{
if(a.x == b.x)return a.y < b.y;
return a.x < b.x;
}
double dis(node a, node b)
{
return sqrt(1.0* (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int cross(node a, node b, node c)
{
return (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
}
double convex(int len)
{
if(len == 1)
return templen;
if(len == 2)
return templen - dis(retree[0],retree[1])*2;
sort(retree.begin(), retree.end(), cmp);
int m = 0;
for(int i = 0; i < len; i++)
{
while(m > 1 && cross(tubao[m-2], tubao[m-1], retree[i]) <= 0)
m--;
tubao[m++] = retree[i];
}
int k = m;
for(int i = len - 2; i >= 0; i--)
{
while(m > k && cross(tubao[m-2], tubao[m-1], retree[i]) <= 0)
m--;
tubao[m++] = retree[i];
}
if(len > 1)
m--;
double length = 0;
for(int i = 1; i < m; i++)
{
length += dis(tubao[i-1],tubao[i]);
}
length += dis(tubao[m-1],tubao[0]);
return templen - length;
}
int main()
{
int t,cas = 1;
while(~scanf("%d", &t))
{
if(t == 0)break;
int ansvalue = 1 << 30;
int ansi = 0,ansnum = 0;
double anslen = 0;
for(int i = 0; i < t; i++)
scanf("%d%d%d%lf", &e[i].x, &e[i].y, &e[i].v, &e[i].l);
for(int i = 1; i < (1 << t) - 1; i++)//全砍掉和全不砍掉没有意义,不用讨论
{
retree.clear();
tempvalue = 0, templen = 0;
for(int j = 0; j < t; j++)
{
if(i & (1 << j))
{
templen += e[j].l;
tempvalue += e[j].v;
}
else
{
retree.push_back(e[j]);
}
}
if(tempvalue > ansvalue)continue;//大了就不用管了,直接走你
double now = convex(retree.size());
if(now >= 0)
{
if(tempvalue < ansvalue)
{
ansvalue = tempvalue;
ansi = i;
ansnum = t - retree.size();
anslen = now;
}
else if(tempvalue == ansvalue && ansnum > t - retree.size())
{
ansi = i;
ansnum = t - retree.size();
anslen = now;
}
}
}
printf("Forest %d\nCut these trees:",cas++);
for(int i=0;i<t;i++)
if( (1<<i) & ansi) printf(" %d", i+1 );
printf("\nExtra wood: %.2f\n\n",anslen);
}
return 0;
}