1. 程式人生 > >CF 814D

CF 814D

struct spa size type += 容易 設計 long str

這個題的DP做法感覺好神奇...

容易發現圓的包含關系是一個森林,我們設計狀態是F[i][0/1][0/1]表示以i為根的子樹中,第一個集合有偶數/奇數個圓包含它,第二個集合有偶數/奇數個圓包含它時能取得的最大權值,那麽我們就可以比較容易的轉移了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<vector>
 6 using namespace std;
 7 #define maxn 1005
 8 typedef long
long LL; 9 struct Vergil 10 { 11 int x,y,r; 12 }t[maxn]; 13 int n,father[maxn]; 14 LL f[maxn][2][2],ans; 15 vector<int> son[maxn]; 16 17 LL dist(int o1,int o2) 18 { 19 return (LL)(t[o1].x-t[o2].x)*(t[o1].x-t[o2].x)+(LL)(t[o1].y-t[o2].y)*(t[o1].y-t[o2].y); 20 } 21 22 inline bool
bh(int o1,int o2) 23 { 24 return dist(o1,o2)<(LL)t[o1].r*t[o1].r; 25 } 26 27 void dfs(int u) 28 { 29 int siz=son[u].size(); 30 LL g[2][2]={{0}}; 31 for (int i=0;i<siz;i++) 32 { 33 int v=son[u][i]; 34 dfs(v); 35 for (int j=0;j<2;j++) 36 for
(int k=0;k<2;k++) 37 g[j][k]+=f[v][j][k]; 38 } 39 LL w=(LL)t[u].r*t[u].r; 40 for (int i=0;i<2;i++) 41 for (int j=0;j<2;j++) 42 f[u][i][j]=max(g[i^1][j]+w*(i==0?1:-1),g[i][j^1]+w*(j==0?1:-1)); 43 } 44 45 int main() 46 { 47 scanf("%d",&n); 48 for (int i=1;i<=n;i++) scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].r); 49 for (int i=1;i<=n;i++) 50 for (int j=1;j<=n;j++) 51 { 52 if (t[j].r<=t[i].r) continue; 53 if (!bh(j,i)) continue; 54 if (!father[i]||t[father[i]].r>t[j].r) father[i]=j; 55 } 56 for (int i=1;i<=n;i++) 57 if (father[i]) son[father[i]].push_back(i); 58 for (int i=1;i<=n;i++) 59 if (!father[i]) 60 { 61 dfs(i); 62 ans+=f[i][0][0]; 63 } 64 printf("%.10f\n",ans*acos(-1)); 65 return 0; 66 }

CF 814D