【poj 1873】 凸包加枚举

题目链接:https://vjudge.net/problem/POJ-1873

题意:给你若干个点(最多15),每个点有两个值 v,l。让你删去某些点,使得总和v最小,且总和l能够包住剩余没选点。直接凸包加枚举OK了。发现G++输出得用%f。。。。。还我1A

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 using namespace std;
  7 const int N=20;
  8 #define eps 1e-8
  9 #define inf 0x3f3f3f3f
 10 int sgn(double x){
 11     if(fabs(x)<eps) return 0;
 12     if(x<0) return -1;
 13     return 1;
 14 } 
 15 struct Point{
 16     double x,y,l;
 17     int v;
 18     Point operator - (const Point& b)const{
 19         return (Point){x-b.x,y-b.y};
 20     }
 21     double operator ^ (const Point& b)const{
 22         return x*b.y-b.x*y; 
 23     }
 24 }p[N],a[N],p0;
 25 int sta[N];
 26 int n;
 27 bool vis[N];        
 28 double dist(Point a,Point b){
 29     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 30 }          
 31 bool cmp(Point a,Point b){
 32     if(atan2(a.y-p0.y,a.x-p0.x)!=atan2(b.y-p0.y,b.x-p0.x)){
 33         return (atan2(a.y-p0.y,a.x-p0.x)<atan2(b.y-p0.y,b.x-p0.x));        
 34     }
 35     return a.x<b.x;
 36 }   
 37 double graham(int cnt){
 38     if(cnt<2) return 0;
 39     if(cnt==2) return 2*dist(a[1],a[2]);
 40     p0=a[1];
 41     int k=1;
 42     for(int i=2;i<=cnt;++i){
 43         if((p0.y > a[i].y) || ((p0.y==a[i].y) && (p0.x>a[i].x))){
 44             p0=a[i];
 45             k=i;
 46         }
 47     }
 48     a[k]=a[1];
 49     a[1]=p0;
 50     sort(a+2,a+1+cnt,cmp);
 51     sta[0]=1; sta[1]=2;
 52     int top=1;
 53     for(int i=3;i<=cnt;++i){
 54         while(top>0&&((a[i]-a[sta[top-1]])^(a[sta[top]]-a[sta[top-1]])) >= 0) --top;
 55         sta[++top]=i;
 56     }
 57     double ans=0;
 58     for(int i=0;i<top;++i) ans+=dist(a[sta[i]],a[sta[i+1]]);
 59     ans+=dist(a[sta[0]],a[sta[top]]);
 60     return ans;
 61 }               
 62 int ans[N];
 63 int main(){
 64     int n; 
 65     int cas=0;
 66     while(~scanf("%d",&n) && n){
 67         for(int i=0;i<n;++i) scanf("%lf %lf %d %lf",&p[i].x,&p[i].y,&p[i].v,&p[i].l);
 68         int ansv=inf,ansn=inf;
 69         double anslef;
 70         for(int i=0;i<(1<<n);++i){
 71             memset(vis,0,sizeof(vis));
 72             int temv=0,temn=0;
 73             double teml=0;
 74             int cnt=0;
 75             for(int j=0;j<n;++j){
 76                 if((1<<j) & i){
 77                     vis[j]=1;
 78                     ++temn;
 79                     temv+=p[j].v;
 80                     teml+=p[j].l;
 81                 }
 82                 else a[++cnt]=p[j];
 83             }
 84             //cerr<<i<<' '<<temv<<' '<<temn<<' '<<teml<<endl;
 85             if(temv > ansv || (temv==ansv && temn > ansn)) continue;
 86             double used=graham(cnt);
 87             //cerr<<i<<' '<<used<<endl;
 88             if(used <= teml){
 89                 ansv=temv;
 90                 anslef=teml-used;
 91                 ansn=0;
 92                 for(int u=0;u<n;++u) if(vis[u]) ans[++ansn]=u;
 93             }
 94         }
 95         printf("Forest %d\n",++cas);
 96         printf("Cut these trees: ");
 97         for(int i=1;i<=ansn;++i) printf("%d ",ans[i]+1);
 98         printf("\n");
 99         printf("Extra wood: %.2f\n",anslef);
100         puts("");
101     }
102 }
View Code

 

posted @ 2019-09-22 23:38  小布鞋  阅读(132)  评论(0编辑  收藏  举报