bzoj1043 下落的圓盤

2022-05-01 07:18:12 字數 1610 閱讀 7489

time limit: 10 sec  memory limit: 162 mb

submit: 1587  solved: 669

[submit][status][discuss]

有n個圓盤從天而降,後面落下的可以蓋住前面的。求最後形成的封閉區域的周長。看下面這副圖, 所有的紅

色線條的總長度即為所求.

第一行為1個整數n,n<=1000

接下來n行每行3個實數,ri,xi,yi,表示下落時第i個圓盤的半徑和圓心座標.

最後的周長,保留三位小數

21 0 0

1 1 0

10.472

分析:一開始的思路是每增加乙個圓盤,看它能覆蓋到被計入答案的區域,答案減掉這個長度.這個想法似乎是可行的,但是維護每個圓盤哪些位置被覆蓋了非常困難.

換個思路,考慮每個圓盤對答案的貢獻:原周長-被後來的圓盤覆蓋的周長.實際上後面一部分就是要求周長並,可以將圓拆成一條線段,規定乙個起點和終點.但是這樣的話還要求兩個圓的交點,不好處理.乙個比較好的方法是記錄被覆蓋部分的圓心角,放到[0,2π)這個區間裡.利用兩個圓心的極角和圓心角可以比較容易地計算.圓心角可以通過餘弦定理得到.需要注意的是左右端點<0和≥2π的情況.

還要判斷兩圓是否是包含/相離關係.

最後怎麼求周長並?先把弧度並給求出來,乘上半徑就是了.具體方法是在左端點+1,右端點-1,用cnt統計+1,-1的和,如果cnt > 0,則ans -= 第i個弧度-第i-1個弧度.ans初始化為2π.(有點複雜,結合**更好理解)

#include #include 

#include

#include

#include

using

namespace

std;

const

double pi = acos(-1.0),eps = 1e-8

;int

n,tot;

double

ans,sum;

struct

node

e[1010

];struct

node2

p[10010

];double

d(node a,node b)

bool

cmp(node2 a,node2 b)

intmain()

if (dist > fabs(e[i].r - e[j].r) && dist <= e[i].r +e[j].r) //必須要相交不能分離

if (l >= 0 && r <= 2 *pi)

else

if (l < 0

)

else}}

if(flag)

continue

; ans += e[i].r * 2 *pi;

if (!tot)

continue

; sort(p + 1,p + 1 +tot,cmp);

for(int j = 1; j <= tot; j++)

} printf(

"%.3lf\n

",ans);

return0;

}

1043 HAOI2008 下落的圓盤

time limit 10 sec memory limit 162 mb submit 1725 solved 743 submit status discuss 有n個圓盤從天而降,後面落下的可以蓋住前面的。求最後形成的封閉區域的周長。看下面這副圖,所有的紅 色線條的總長度即為所求.第一行為1個...

BZOJ1043 HAOI2008 下落的圓盤

每個圓盤只會受到後邊的圓盤的影響 所以算一下每個圓盤和後邊的圓盤相交的圓心角,然後求個並即可 可以用餘弦定理 複雜度n 2 log n 注意特判沒有交 include include include include include include include include include in...

bzoj1043 HAOI2008 下落的圓盤

題目鏈結 有n個圓盤從天而降,後面落下的可以蓋住前面的。求最後形成的封閉區域的周長。直接模擬,求出當前圓盤與之前的所有的圓盤的交點,用極角表示,模擬結束後求出每個圓盤未被覆蓋的角度即可。include include include include include include using nam...