計算幾何(ZOJ 3783,Coins Game)

2021-07-31 06:26:42 字數 2440 閱讀 5200

一開始re,不知道咋回事,後來發現原來是assert(0)搞的(前面寫的後面給忘了),說明我沒有找到任何乙個與移動硬幣相切的固定硬幣。

當時覺得應該是精度的問題,但是試了各種eps的值依然找不到。

我判定相切的辦法是求兩個圓交點的個數是不是一。後來覺得沒必要這樣判定,有更好的辦法,那就是直接判定半徑和是否等於圓心距,然後就ac了。

經過測試後發現錯誤原因是相切的時候函式判斷有兩個交點。理論上來說判斷點是否重合的函式應該會更嚴格才對,所以誤差應該是在計算兩點座標的時候就被放大了,一旦涉及到角度的問題一般誤差都會被放大很多。這個誤差似乎沒有什麼好的辦法可以避免,所以說對於計算幾何的題目來說,每個判斷都應該在誤差沒被放大的時候用誤差最小的判斷方法來判斷,否則就可能出現錯誤。嘗試了各種eps的值依然不行,我也不清楚為什麼會這樣,可能是因為當eps足夠寬容的時候,另一些判斷又被掩蓋了。所以說有時候調整eps是沒有用,或者說很難成功的。我們更應該把每個細節都處理得盡量精確。

雖然說被卡了,但是資料還是很水的,就算我去掉了一些增加魯棒性的**,也可以ac。如果去掉那段**的話,我自己是能找到一些簡單資料把**跑成死迴圈的。

具體思路就是圓心走過的距離除以圓周長就是轉過的圈數,乘以360度就是轉過的角度數。

然後模擬滾動一遍計算圓心走過的距離就好了。

一些注意的地方,angle(vector v)函式可以返回向量v與x軸之間的夾角,逆時針為正,順時針為負,範圍是(-pi,pi]。

實現方法是呼叫atan2()函式,這個函式可以返回方位角(與現實中的方位角定義有所不同,唯一區別是值減少了pi),即向量v與y軸之間的夾角,順時針為正,逆時針為負,範圍是(-pi,pi],所以要呼叫atan2(v.y.v.x)才對。

因為我們要順時針旋轉,所以極角要從大到小排序。(其實逆時針模擬也一樣,相應的極角就從小到大排序)

為了保證能轉一圈找到下乙個點,所以每個點都要複製乙個極角小2*pi的點。(如果逆時針,就大2*pi)

**

#includeusing namespace std;

const int maxn = 1010;

const double pi = acos(-1);

struct point

void read()

bool operator < (const point& rhs) const

};typedef point vector;

const double eps = 1e-10;

int dcmp(double x)

bool operator == (const point& a,const point& b)

vector operator + (vector a,vector b)

vector operator - (point a,point b)

vector operator * (vector a,double t)

vector operator / (vector a,double t)

double dot(vector a,vector b)

double len(vector a)

struct circle

point point(double a)

if(dcmp(c1.r+c2.r-d)<0) return 0;

if(dcmp(fabs(c1.r-c2.r)-d)>0) return 0;

double a = angle(c2.c-c1.c);

double da = acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));

point p1 = c1.point(a-da);

point p2 = c1.point(a+da);

sol.push_back(p1);

if(p1==p2) return 1;

sol.push_back(p2);

return 2;

}int n;

circle c[maxn];

circle o,s;

int kkk;

void gets()

sort(r,r+sb.size(),cmp1);

k+=r[0];

}//puts("----------");

//for(int i=0;i<(int)nowc.vec.size();i++) printf("(%lf %lf) ",nowc.vec[i].x,nowc.vec[i].y);

//puts("\n----------");

len+=nowc.r*(nowp.ang-nowc.vec[k].ang);

nowp=nowc.vec[k];

if(nowp.bel==-1) break;

nowc=c[nowp.bel];

}printf("%.10lf\n",len/pi*180/o.r);

}int main()

zoj 3203 Light Bulb 計算幾何

題意是給定如圖的h,h,d,求最大的影子l。如圖所示,設x,y。由三角形相似得,x y h y d 解得 y x d h x 由三角形相似得,x y h y l x 帶入y,解得 l x d h x h x 對l 求一階導數,並令l 0,得 x h sqrt d h h 因為 x 必定小於 h,所以...

zoj 3537 區間dp 計算幾何

題意 給定n個點的座標,先問這些點是否能組成乙個凸包,如果是凸包,問用不相交的線來切這個凸包使得凸包只由三角形組成,根據costi,j xi xj yi yj p算切線的費用,問最少的切割費用。題解 點我 2015 07 20 專題複習 稍微修改了一下,順便發現題號寫錯了 1 include2 in...

ZOJ 1049 幾何算數題

1049 選一座標點建房。河水淹沒區域是半圓形,每年擴大50平方英里。問幾年能淹到房子。img sample input 2 1.0 1.0 25.0 0.0 sample output property 1 this property will begin eroding in year 1.pr...