洛谷 P4515 [COCI2009-2010#6] XOR
阿新 • • 發佈:2019-03-19
歸納 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 {View Code12 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 }
洛谷 P4515 [COCI2009-2010#6] XOR