|
Posted on 2010-05-05 21:04 Uriel 阅读(560) 评论(2) 编辑 收藏 引用 所属分类: POJ 、 计算几何
惭愧,这题从中午写到晚上,一开始一直卡着调也调不了,搞到晚上没办法换了个凸包模板,然后历经各种NC错误终于AC。。 浙大模板凸包那里应该没什么问题,用过多少次了,应该是自己写挂了吧。。- - 题意是有n棵树,每棵的坐标,价值和长度已知,要砍掉若干根,用他们围住其他树,问损失价值最小的情况下又要长度足够围住其他树,砍掉哪些树。。 Discuss称这题为Final的水题。。于是我也水过去了。。枚举+构造凸包判可行。。代码如下。。凸包那里可以无视。。- -直接贴模板的。。
/**//* Problem: 1873 User: Uriel Memory: 192K Time: 454MS Language: C++ Result: Accepted */ #include<math.h> #include<stdio.h> #include<stdlib.h> #include<algorithm> using namespace std;
struct point { int flag; double x,y,v,l; };
point P[100],convex[100],p1[100],p2[100],p[100]; double resl,suml,sumv,minv,ans; int n,ansn;
double Dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
double multiply(const point& sp,const point& ep,const point& op) { return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y)); }
bool cmp(point a,point b) { return a.flag < b.flag; }
int partition(point a[],int p,int r) { int i=p,j=r+1,k; double ang,dis; point R,S; k=(p+r)/2; R=a[p];a[p]=a[k];a[k]=R;R=a[p]; dis=Dis(R,a[0]); while(1) { while(1) { ++i; if(i>r) { i=r; break; } ang=multiply(R,a[i],a[0]); if(ang>0) break; else if(ang==0) { if(Dis(a[i],a[0])>dis) break; } } while(1) { --j; if(j<p) { j=p; break; } ang=multiply(R,a[j],a[0]); if(ang<0) break; else if(ang==0) { if(Dis(a[j],a[0])<dis) break; } } if(i>=j)break; S=a[i]; a[i]=a[j]; a[j]=S; } a[p]=a[j]; a[j]=R; return j; }
void anglesort(point a[],int p,int r) { if(p<r) { int q=partition(a,p,r); anglesort(a,p,q-1); anglesort(a,q+1,r); } }
/**//*PointSet传入散点,凸包上的点存在ch,n为点数,len为凸包顶点数*/ void Graham_scan(point PointSet[],point ch[],int n,int &len) { int i,k=0,top=2; point tmp; for(i=1;i<n;i++) if ( PointSet[i].x<PointSet[k].x || (PointSet[i].x==PointSet[k].x) && (PointSet[i].y<PointSet[k].y)) k=i; tmp=PointSet[0]; PointSet[0]=PointSet[k]; PointSet[k]=tmp; anglesort(PointSet,1,n-1); if(n<3) { len=n; for(int i=0;i<n;i++) ch[i]=PointSet[i]; return ; } ch[0]=PointSet[0]; ch[1]=PointSet[1]; ch[2]=PointSet[2]; for (i=3;i<n;i++) { while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--; ch[++top]=PointSet[i]; } len=top+1; }
int main() { int cse,g=1,i,j,k1,M,k2; while(scanf("%d",&n),n) { for(i=0;i<n;i++) { scanf("%lf %lf %lf %lf",&P[i].x,&P[i].y,&P[i].v,&P[i].l); P[i].flag=i+1; } minv=1e20; for(i=0;i<(1<<n);i++) { k1=0;k2=0; sumv=0;suml=0; for(j=0;j<n;j++) { if(!(i & (1<<j))) { p1[k1].x=P[j].x; p1[k1].y=P[j].y; k1++; } else { p2[k2].flag=P[j].flag; sumv+=P[j].v; suml+=P[j].l; k2++; } } Graham_scan(p1,convex,k1,M); resl=0; for(int j=0;j<M-1;j++) { resl+=Dis(convex[j],convex[j+1]); } resl+=Dis(convex[0],convex[M-1]); if(resl<=suml && sumv<minv) { ans=suml-resl; minv=sumv; ansn=k2; for(j=0;j<k2;j++)p[j].flag=p2[j].flag; } } printf("Forest %d\n",g++); printf("Cut these trees:"); for(i=0;i<ansn;i++)if(p[i].flag!=p[i-1].flag)printf(" %d",p[i].flag); printf("\n"); printf("Extra wood: %.2lf\n\n",ans); } // system("PAUSE"); return 0; }
Feedback
# re: POJ 1873 The Fortified Forest---凸包+枚举 回复 更多评论
2012-03-20 20:24 by
5 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 崩溃数据
# re: POJ 1873 The Fortified Forest---凸包+枚举 回复 更多评论
2012-03-20 21:02 by
@debuger 谢谢提醒,原来没有考虑共线的情况,有共线时凸包那里会有bug 似乎改成这样就可以 while (multiply(PointSet[i], ch[top], ch[top - 1]) >= 0 && top >= 1) top--; 还有问题的话欢迎指教~
|