1. 程式人生 > >洛谷 P4515 [COCI2009-2010#6] XOR

洛谷 P4515 [COCI2009-2010#6] XOR

歸納 pow esp ons com mes clas ont show

題意

平面直角坐標系中有一些等腰直角三角形,且直角邊平行於坐標軸,直角頂點在右下方,求奇數次被覆蓋的面積。N<=10。輸入為x,y,r,分別表示三角形頂點的坐標與三角形的邊長。

如:

技術分享圖片總面積為0.5+2+4.5-0.5-0.5=6


思考

看到數據範圍,就肯定是優美的暴力。

這題思路很清奇。首先我們要先求出任意幾個三角形面積的交,但我們知道兩個之間的關系就行了,因為這樣特殊的三角形最後的交必然一模一樣(只是縮放了)。

為了算出面積的交,我們先考慮算出最後交的三角形的邊長,因為這樣子平方一下除以二就是面積。

我們還知道,交的邊長關於x,y,r一定是一次關系,至少是只有一次項,而且沒有常數。我們不妨考慮這些三角形的y都相等。

技術分享圖片如圖,這種情況下的邊長為max{0,min{xi+ri}-max{xi}},即若有交,x+r一定要最小,這樣所有三角形才能夠到,再減去x最大的一個。若沒交,不難證明結果小於0。

同樣地,x都相等時邊長為max{0,min{yi+ri}-max{yi}},於是我們考慮合並起來。

經過打表(即我不會證明),我們發現最後的結果為max{0,min{xi+yi+ri}-max{xi}-max{yi}}。

這樣完成了第一步。然後容斥考慮面積並。看看每個重疊的三角形對答案的貢獻:

技術分享圖片

不難發現,若有n個三角形重疊,則數量上的貢獻為(-2)^(n-1),具體證明歸納法。

dfs一下即可。

代碼

技術分享圖片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const ll maxn=15;
 5 const ll inf=INT_MAX;
 6 ll max(ll x,ll y){return x>y?x:y;}
 7 ll x[maxn],y[maxn],r[maxn],n,ans;
 8 void dfs(ll s,ll maxx,ll maxy,ll maxc,ll g)
 9 {
10     if(s==n+1)
11     {
12 if(g>=1)ans+=pow(-2,g-1)*max(0,maxc-maxx-maxy)*max(0,maxc-maxx-maxy); 13 return; 14 } 15 dfs(s+1,maxx,maxy,maxc,g); 16 dfs(s+1,max(maxx,x[s]),max(maxy,y[s]),min(maxc,x[s]+y[s]+r[s]),g+1); 17 } 18 int main() 19 { 20 ios::sync_with_stdio(false); 21 cin>>n; 22 for(int i=1;i<=n;++i)cin>>x[i]>>y[i]>>r[i]; 23 dfs(1,0,0,inf,0); 24 cout<<fixed<<setprecision(1)<<double(ans)/2<<endl; 25 return 0; 26 }
View Code

洛谷 P4515 [COCI2009-2010#6] XOR