ACM必做50题的解题计算几何.docx
- 文档编号:17648000
- 上传时间:2023-04-24
- 格式:DOCX
- 页数:30
- 大小:20.93KB
ACM必做50题的解题计算几何.docx
《ACM必做50题的解题计算几何.docx》由会员分享,可在线阅读,更多相关《ACM必做50题的解题计算几何.docx(30页珍藏版)》请在冰豆网上搜索。
ACM必做50题的解题计算几何
POJ1113WALL
计算几何,求凸包
这题的结果等于这个多边形构成的凸包的周长加上以所给半径为半径的圆的周长
步骤如下:
1)算法首先寻找最最靠下方的点,如果遇到y坐标相同,则寻找x坐标最小的点firstP
2)然后根据所有点相对于firstP的偏角的大小进行排序,遇到偏角相等的,只取距离
firstP最远的点(排序利用自己手写的快排)
3)然后利用Graham算法求凸包
4)最后直接求职
#include
#include
#definePI3.1415926
#defineMAX_N1000
usingnamespacestd;
//存储原始输入的坐标值,rad是输入的半径
doublecord[MAX_N+2][2],rad;
intseq[MAX_N+2];
intstack[MAX_N+2];
intn,top;
intfirstP;
intrealN;
voidswap(intpos1,intpos2)
{
inttemp=seq[pos1];
seq[pos1]=seq[pos2];
seq[pos2]=temp;
}
intdir(intnodes,intnode1,intnode2)
{
doublex1=cord[node1][0],y1=cord[node1][1];
doublex2=cord[node2][0],y2=cord[node2][1];
doublesx=cord[nodes][0],sy=cord[nodes][1];
return(x2-sx)*(y1-sy)-(x1-sx)*(y2-sy);
}
doublegetDist(intnode1,intnode2)
{
doublex1=cord[node1][0],y1=cord[node1][1];
doublex2=cord[node2][0],y2=cord[node2][1];
doubleres=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
returnres;
}
intcompare(intnode1,intnode2)
{
doublex1=cord[node1][0],y1=cord[node1][1];
doublex2=cord[node2][0],y2=cord[node2][1];
doublesx=cord[firstP][0],sy=cord[firstP][1];
doubletype=dir(firstP,node1,node2);
if(type==0)
{
doubledist1=(x1-sx)*(x1-sx)+(y1-sy)*(y1-sy);
doubledist2=(x2-sx)*(x2-sx)+(y2-sy)*(y2-sy);
if(dist1>dist2)
return-2;
elseif(dist1==dist2)
return0;
else
return2;
}
elseif(type>0)
return1;
else
return-1;
}
voidfastSort(intstart,intend)
{
if(start { intcurPos=start; intposS=start,posE=end+1; while(true) { while(compare(seq[++posS],seq[curPos])<0&&posS while(compare(seq[--posE],seq[curPos])>0&&posE>start); if(posS swap(posS,posE); else break; } swap(curPos,posE); fastSort(start,posE-1); fastSort(posE+1,end); } } voidsortSeq() { inti,s=0; for(i=1;i<=n;i++) { //最低最左点不参加排序 if(i==firstP) continue; seq[++s]=i; } realN=n-1; fastSort(1,realN); //清理夹角相同但是距离不同的点,只取举例firstP最远的点 i=1; while(i { s=i+1; //equalanglebutsmallerdistance while(s<=realN&&compare(seq[i],seq[s])==-2) { seq[s]=-1;//置为无效 s++; } i=s; } } //寻找凸包 voidfindQ() { intnodes,node1,node2,type; top=0; stack[top++]=firstP; ints=1; intc=0; while(c<2) { if(seq[s]! =-1) { c++; stack[top++]=seq[s]; } s++; } for(;s<=realN;s++) { if(seq[s]==-1) continue; while(true) { nodes=stack[top-2]; node1=stack[top-1]; node2=seq[s]; type=dir(nodes,node1,node2); if(type>=0) top--; else break; } stack[top++]=seq[s]; } } doublegetRes() { doubletotalDist=0; intlastNode=firstP; intcurNode; while(top>0) { curNode=stack[--top]; totalDist+=getDist(lastNode,curNode); lastNode=curNode; } //totalDist+=getDist(lastNode,firstP); totalDist+=2*PI*rad; returntotalDist; } intmain() { inti; cin>>n>>rad; intminX=INT_MAX,minY=INT_MAX; for(i=1;i<=n;i++) { cin>>cord[i][0]>>cord[i][1]; if((cord[i][1] { firstP=i; minX=cord[i][0]; minY=cord[i][1]; } } sortSeq(); findQ(); doubleres=getRes(); printf("%.0f\n",res); return0; } POJ1292WillIndianaJonesGetThere? 题目大意: 英雄Jones现在在位置1,有人在位置2呼救,所以他要过去救他,但是有个条件,他必须在墙上走,其实就是说他只能在图示的线段上走,但是线段间有空隙,所以要用一个长板搭在线段间才能从一个线段到另外一个线段,问怎么找到一个路径使得要使用的长板最小。 题目一眼看下去还比较复杂,毕竟你看到是一堆线段,但是这时候一个很直观的思想就是枚举两个线段间的距离,将每个线段都看成是一个节点,这样其实就化为了一个简单的有向图,这时要寻找最短的长板其实最小生成树的问题,利用Prim算法就可以解决,本题的难处就在于计算线段间的距离跟最小生成树的实现。 计算线段间距离写得很乱,大家包容。 #include #include #include floathorDist(intx1,inty1,intL1,intx2,inty2,intL2) { if(x2>x1) { if(x2>x1+L1) { returnsqrt((float)((x2-x1-L1)*(x2-x1-L1)+(y2-y1)*(y2-y1))); } else { returnabs(y2-y1); } } else { if(x1>x2+L2) { returnsqrt((float)((x1-x2-L2)*(x1-x2-L2)+(y2-y1)*(y2-y1))); } else { returnabs(y2-y1); } } } floatverDist(intx1,inty1,intL1,intx2,inty2,intL2) { returnhorDist(y1,x1,-L1,y2,x2,-L2); } floathor2verDist(intx1,inty1,intL1,intx2,inty2,intL2) { intxHor,yHor,LHor,xVer,yVer,LVer; if(L1>0) { xHor=x1; yHor=y1; LHor=L1; xVer=x2; yVer=y2; LVer=-L2; } else { xHor=x2; yHor=y2; LHor=L2; xVer=x1; yVer=y1; LVer=-L1; } if(yVer<=yHor&&yHor<=(yVer+LVer)) { if(xHor<=xVer&&xVer<=(xHor+LHor)) { return0.0; } else { if(xVer>(xHor+LHor)) { returnxVer-xHor-LHor; } else { returnxHor-xVer; } } } else { if(xHor<=xVer&&xVer<=(xHor+LHor)) { if(yHor>(yVer+LVer)) { returnyHor-yVer-LVer; } else { returnyVer-yHor; } } else { if(xVer>(xHor+LHor)) { if(yHor>(yVer+LVer)) { returnsqrt((float)(pow((float)(yHor-yVer-LVer),2)+pow((float)(xVer-xHor-LHor),2))); } else { returnsqrt((float)(pow((float)(yHor-yVer),2)+pow((float)(xVer-xHor-LHor),2))); } } else { if(yHor>(yVer+LVer)) { returnsqrt((float)(pow((float)(yHor-yVer-LVer),2)+pow((float)(xVer-xHor),2))); } else { returnsqrt((float)(pow((float)(yHor-yVer),2)+pow((float)(xVer-xHor),2))); } } } } } template TMinFloat(constT&a,constT&b) { return(a a: b; }; floatdist(intx1,inty1,intL1,intx2,inty2,intL2) { if(L1==0) { if(L2==0) { returnsqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))); } elseif(L2<0) { intyTemp=0; intxTemp=0; yTemp=y2-L2; xTemp=x2; if(y2<=y1&&y1<=yTemp) { returnabs(x1-x2); } else { returnMinFloat(sqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))),sqrt((float)(pow((float)(x1-xTemp),2)+pow((float)(y1-yTemp),2)))); } } else { intyTemp=0; intxTemp=0; yTemp=y2; xTemp=x2+L2; if(x2<=x1&&x1<=xTemp) { returnabs(y1-y2); } else { returnMinFloat(sqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))),sqrt((float)(pow((float)(x1-xTemp),2)+pow((float)(y1-yTemp),2)))); } } } if(L2==0) { if(L1==0) { returnsqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))); } elseif(L1<0) { intyTemp=0; intxTemp=0; yTemp=y1-L1; xTemp=x1; if(y1<=y2&&y2<=yTemp) { returnabs(x1-x2); } else { returnMinFloat(sqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))),sqrt((float)(pow((float)(x2-xTemp),2)+pow((float)(y2-yTemp),2)))); } } else { intyTemp=0; intxTemp=0; yTemp=y1; xTemp=x1+L1; if(x1<=x2&&x2<=xTemp) { returnabs(y1-y2); } else { returnMinFloat(sqrt((float)(pow((float)(x1-x2),2)+pow((float)(y1-y2),2))),sqrt((float)(pow((float)(x2-xTemp),2)+pow((float)(y2-yTemp),2)))); } } } if(L1*L2>0) { if(L1>0) { returnhorDist(x1,y1,L1,x2,y2,L2); } else { returnverDist(x1,y1,L1,x2,y2,L2); } } else { returnhor2verDist(x1,y1,L1,x2,y2,L2); } } constintMaxValue=1005; constfloatMAXFLOAT=10000000000.0; floatDistArray[MaxValue][MaxValue]; structWALL { intx; inty; intlength; }; WALLwalls[MaxValue]; structPointInfo { intparent; floatpath; boolgoon; boolcomplete; }; PointInfoinfo[MaxValue]; floatPrim(intN) { inti; while(true) { floatminValue=MAXFLOAT; intminIndex=-1; for(i=0;i { if(info[i].goon&&! info[i].complete) { if(info[i].path { minValue=info[i].path; minIndex=i; } } } info[minIndex].complete=true; if(minIndex==1) { break; } for(i=0;i { if(! info[i].complete&&i! =minIndex) { info[i].goon=true; if(DistArray[minIndex][i] { info[i].path=DistArray[minIndex][i]; info[i].parent=minIndex; } } } } floatlength=0.0; i=1; while(info[i].parent! =-1) { floattemp=DistArray[info[i].parent][i]; if(length { length=temp; } i=info[i].parent; } returnlength; } intmain() { while(true) { intN; inti; intj; scanf("%d",&N); if(N==0) { break; } for(i=0;i { scanf("%d%d%d",&walls[i].x,&walls[i].y,&walls[i].length); } memset(DistArray,0,sizeof(DistArray)); for(i=0;i { for(j=i+1;j { DistArray[i][j]=dist(walls[i].x,walls[i].y,walls[i].length,walls[j].x,walls[j].y,walls[j].length); DistArray[j][i]=DistArray[i][j]; } } for(i=1;i { info[i].path=MAXFLOAT; info[i].goon=false; info[i].complete=false; info[i].parent=0; } info[0].path=0; info[0].goon=true; info[0].complete=false; info[0].parent=-1; floatlength=Prim(N); printf("%.2f\n",length); } return0; } poj2148——ColortheMap——线段部分重合 本题如果把图建完了,其实就是枚举总颜色数后dfs即可。 所以本题的关键就是建图啦。 而建图重要的是解决Twocountriesareconsideredtobe"adjacent"ifanyoftheirterritoriesshareaborderofnon-zero length.亦即解决两条线段部分重合的问题。 解决部分重合的代码如下: intcross(constint&ax,constint&ay,constint&bx,constint&by) { returnax*by-bx*ay; } intdot(constint&ax,constint&ay,constint&bx,con
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 50 解题 计算 几何