poj1873 The Fortified Forest 凸包+枚举 水题

来源:互联网 发布:azw3电脑打开软件 编辑:程序博客网 时间:2024/06/06 02:53
/*poj1873 The Fortified Forest 凸包+枚举 水题用小树林的木头给小树林围一个围墙每棵树都有价值求消耗价值最低的做法,输出被砍伐的树的编号和剩余的木料若砍伐价值相同,则取砍伐数小的方案。*/#include<stdio.h>#include<math.h>#include <algorithm> #include <vector>using namespace std;const double eps = 1e-8;  struct point{double x,y;};struct exinfo{int v,l;}info[20];int n;point dian[20],zhan[20];//////////////////////////////////////////////////point *mo_dian;double mo_distance(point p1,point p2){    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}double mo_xmult(point p2,point p0,point p1)//p1在p2左返回负,在右边返回正{    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}bool mo_ee(double x,double y){double ret=x-y;if(ret<0) ret=-ret;if(ret<eps) return 1;return 0;}bool mo_gg(double x,double y)  {   return x > y + eps;} // x > y   bool mo_ll(double x,double y)  {   return x < y - eps;} // x < y   bool mo_ge(double x,double y) {   return x > y - eps;} // x >= y   bool mo_le(double x,double y) {   return x < y + eps;}     // x <= y   bool mo_cmp(point a,point b)   // 第一次排序   {      if( mo_ee(a.y ,b.y ) )          return mo_ll(a.x, b.x);      return mo_ll(a.y,b.y);  }  bool mo_cmp1(point a,point b)  // 第二次排序   {      double len = mo_xmult(b,mo_dian[0],a);      if( mo_ee(len,0.0) )          return mo_ll(mo_distance(mo_dian[0],a),mo_distance(mo_dian[0],b));      return mo_gg(len,0.0);  }  int mo_graham(int n,point *dian,point *stk){int i,top=1;mo_dian=dian;sort(mo_dian,mo_dian+n,mo_cmp);      sort(mo_dian+1,mo_dian+n,mo_cmp1);  stk[0]=mo_dian[0];      stk[1]=mo_dian[1];  for(i=2;i<n;++i)      {          while(top>0&&mo_xmult(mo_dian[i],stk[top-1],stk[top])<=0) --top;          stk[++top]=mo_dian[i];      }      return top+1;  }////////void getpoint(int tree,point *dian,point *work,vector<int> &cut,int &n_cut,int &n_sheng,int &cutv,int &cutl){cut.clear();cutv=0;cutl=n_sheng=n_cut=0;int i;for(i=0;i<n;++i){if((1<<i)&tree)//cut{cut.push_back(i);n_cut++;cutv+=info[i].v;cutl+=info[i].l;}else{work[n_sheng++]=dian[i];}}}double zhou(point *dian,int n){int i;double ret=0;for(i=0;i<n;++i){ret+=sqrt((dian[(i+1)%n].x-dian[i].x)*(dian[(i+1)%n].x-dian[i].x)+(dian[(i+1)%n].y-dian[i].y)*(dian[(i+1)%n].y-dian[i].y));}return ret;}int main(){int i,ncase=1;while(scanf("%d",&n),n){for(i=0;i<n;++i){scanf("%lf%lf%d%d",&dian[i].x,&dian[i].y,&info[i].v,&info[i].l);}int maxofi=(1<<n)-1;int cutvalue=999999999;double l_sheng;int cutn;vector<int> cut;vector<int> tempcut;point work[20];for(i=0;i<maxofi;++i){int tempcutn,shengyun;int tempcutv,cutl;int ret;double zhouchang;getpoint(i,dian,work,tempcut,tempcutn,shengyun,tempcutv,cutl);if(shengyun==1){zhouchang=0;}else if(shengyun==2){zhouchang=mo_distance(work[0],work[1])*2;}else{ret=mo_graham(shengyun,work,zhan);zhouchang=zhou(zhan,ret);}if(mo_ge(cutl,zhouchang)){if(tempcutv<cutvalue){cutvalue=tempcutv;l_sheng=cutl-zhouchang;cut=tempcut;cutn=tempcutn;}else if(tempcutv==cutvalue&&tempcutn<cutn){cutvalue=tempcutv;l_sheng=cutl-zhouchang;cut=tempcut;cutn=tempcutn;}}}if(ncase!=1) printf("\n");printf("Forest %d\n",ncase++);printf("Cut these trees:");int len=cut.size();for(i=0;i<len;++i){printf(" %d",cut[i]+1);}printf("\n");printf("Extra wood: %.2lf\n",l_sheng);}return 0;}