這題是一題計算幾何題,第一次做計算幾何題,出了很多錯,WA了半天,最後搜到PROXIMA的解題代碼,讀懂後仿照著寫了下,終於AC了,這題主要的痛點在於要從點下手,而不是從角度下手
1、兩條邊掃一圈的時候,最好以點為前進單位,而不要以角度為單位。
雖然這兩種方法是等價的,但是後者需要先把角度相同的點都找出來,還要統計各個角度上分別有幾個點,這要花費一些初始化的時間。然而,在最差情況下,每個點所在的角度都可以是不同的,那麼以角度為前進單位就完全沒有必要了,還白白浪費了初始化的時間。
2、最好把所有點複製一份,把第二份的所有點的角度都加上 2π。
也就是說,下標為 0 ~ N-1 的點是第一圈,下標為 N ~ 2N-1 的點是第二圈。這樣一來,當掃完了一圈回到開頭時,下標不必回到 0,直接走到 N 繼續下去就好了。這可以節省很多 MOD 運算的時間。#include<iostream><br />#include<algorithm><br />#include<cmath><br />const int MAXNUM=20000;<br />const double PI=atan2(0.0,-1.0);<br />using namespace std;<br />int N,K;<br />struct Point<br />{<br />int x,y;<br />double angle,dist;<br />}ps[MAXNUM];<br />double minangle;<br />bool found[MAXNUM];<br />int cmp(Point a,Point b)<br />{<br />if(a.angle==b.angle)<br />return a.dist<b.dist;<br />else<br />return a.angle<b.angle;<br />}<br />void calMin()<br />{<br />if(K==0||K==1)<br />{<br />minangle=0.00;<br /> return;<br />}<br />minangle=1e100;<br />int end,scount,start;<br />int size=N+N;<br />double newm;<br />for(int i=0;i<N;i++)<br />{<br /> end=-1; scount=0;start=0;<br />for(int j=0;j<size;j++)<br />if(ps[j].dist<=ps[i].dist)<br />{<br />scount++;<br />if(scount==K)<br />{<br /> end=j;<br /> break;<br />}<br />}<br />if(end!=-1)<br />{<br />scount--;end--;<br /> for(int q=end+1;q<size;q++)<br />{<br /> if(ps[q].dist<=ps[i].dist)<br />{<br /> scount++;<br /> while(ps[start].dist>ps[i].dist)start++;<br /> if(scount>K)<br /> {<br />scount--;<br />start++;<br />while(ps[start].dist>ps[i].dist)start++;<br /> }<br />}<br />if((q-start+1)<=N)<br />{<br />newm=(ps[q].angle-ps[start].angle)*ps[i].dist;<br />if(newm<minangle)<br />minangle=newm;<br />}<br />}<br />}<br />}<br />}<br />int main()<br />{<br />int casenum=1;<br />freopen("c://myin.txt","r",stdin);<br /> scanf("%d%d",&N,&K);<br />while(N||K)<br />{<br /> for(int i=0;i<N;i++)<br /> {<br /> scanf("%d%d",&ps[i].x,&ps[i].y);<br /> ps[i].angle=atan2((double)(ps[i].y),(double)(ps[i].x));<br /> ps[i].dist=ps[i].x*ps[i].x+ps[i].y*ps[i].y;<br /> //printf("%d,%d的角度是%.2f/n",ps[i].x,ps[i].y,ps[i]);<br /> }<br /> sort(ps,ps+N,cmp);<br /> for(int j=0;j<N;j++)//將所有點複製一份副本以便節省掃描使用%的開銷<br />{<br /> ps[N+j]=ps[j];<br /> ps[N+j].angle+=PI+PI;<br />}<br /> //for(int u=0;u<N;u++)<br /> //printf("%.2f ",ps[u].angle);<br /> //printf("/n");<br /> calMin();<br /> printf("Case #%d: %.2lf/n",casenum++,minangle/2.0);<br /> scanf("%d%d",&N,&K);<br />}<br /> return 0;<br />}<br />