ACM必做50题的解题计算几何.docx
《ACM必做50题的解题计算几何.docx》由会员分享,可在线阅读,更多相关《ACM必做50题的解题计算几何.docx(30页珍藏版)》请在冰豆网上搜索。
ACM必做50题的解题计算几何
ACM必做50题的解题-计算几何.txt生活,是用来经营的,而不是用来计较的。
感情,是用来维系的,而不是用来考验的。
爱人,是用来疼爱的,而不是用来伤害的。
金钱,是用来享受的,而不是用来衡量的。
谎言,是用来击破的,而不是用来装饰的。
信任,是用来沉淀的,而不是用来挑战的。
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&&posSwhile(compare(seq[--posE],seq[curPos])>0&&posE>start);
if(posSswap(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(const