Bomb Game(求每组俩个圆心选择求固定半径的最大覆盖面积)
题:http://acm.hdu.edu.cn/showproblem.php?pid=3622
题意:给定n组俩个圆心选择,求固定半径能覆盖的最大面积;
分析:显然半径越大面积覆盖越大,所以二分半径;
判断合法就是用2-SAT去连边,以当前为半径的圆会和其他哪些圆冲突就选其对立面连接起来;
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<math.h> using namespace std; #define pb push_back const int M=202; const double eps=1e-5; double x[M],y[M]; vector<int>g[M],rg[M],cb; int cmp[M],vis[M]; int n,m; double dis(int i,int j){ return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } void init(){ cb.clear(); for(int i=0;i<=2*n;i++) g[i].clear(),rg[i].clear(),cmp[i]=0; memset(vis,0,sizeof(vis)); } void addedge(int u,int v){ g[u].pb(v); rg[v].pb(u); } void dfs(int u){ vis[u]=1; for(int i=0;i<g[u].size();i++) if(!vis[g[u][i]]) dfs(g[u][i]); cb.pb(u); } void rdfs(int u,int k){ vis[u]=1; cmp[u]=k; for(int i=0;i<rg[u].size();i++) if(!vis[rg[u][i]]) rdfs(rg[u][i],k); } void scc(){ for(int i=0;i<2*n;i++) if(!vis[i]) dfs(i); int k=0; memset(vis,0,sizeof(vis)); for(int i=cb.size()-1;i>=0;i--){ if(!vis[cb[i]]) rdfs(cb[i],k++); } } bool check(double r){ init(); for(int i=0;i<2*n-2;i++){ int t; if(i%2==0)t=i+2; else t=i+1; for(int j=t;j<2*n;j++) if(dis(i,j)<2*r){ ///cout<<i+1<<" "<<(j^1)+1<<'\n'; /// cout<<j+1<<" "<<(i^1)+1<<'\n'; addedge(i,j^1); addedge(j,i^1); } } scc(); for(int i=0;i<=2*n-2;i+=2) if(cmp[i]==cmp[i+1]) return false; return true; } int main(){ while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++) scanf("%lf%lf%lf%lf",&x[2*i],&y[2*i],&x[2*i+1],&y[2*i+1]); double l=0,r=40000.0; while(r-l>=eps){ double midd=(l+r)/2; if(check(midd)) l=midd; else r=midd; } printf("%.2f\n",r); } return 0; }