題意:
一個遊戲有輪,每輪提供給你兩個座標,你選擇其中一個放置炸彈,到最後會放置個炸彈,要保證任意兩個炸彈的爆炸區域不會相交,每個炸彈的爆炸半徑由你來決定,你的目的是使最小的半徑最大。
題解:
考慮二分半徑,對於半徑,的建立約束關係,利用判斷可行性。時間複雜度。
代碼:
#include<bits/stdc++.h>
using namespace std;
const int N = 500;
int n,m,scc,idx,color[N],low[N],dfn[N];
vector<int> G[N];
bool is_instack[N];stack<int> sta;
void init(int n){
scc=idx=0;
for(int i=1;i<=2*n;i++){
low[i]=dfn[i]=is_instack[i]=color[i]=0;
G[i].clear();
}
while(!sta.empty()) sta.pop();
}
void Tarjan(int u){
low[u]=dfn[u]=++idx;
sta.push(u);is_instack[u]=1;
for(int v:G[u]){
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(is_instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
++scc;
while(1){
int temp=sta.top();
color[temp]=scc;
is_instack[temp]=0;
sta.pop();
if(temp==u) break;
}
}
}
struct Point{
double x,y;
}p[N][2];
double dis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool check(double r){
init(n);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(2.0*r>dis(p[i][0],p[j][0])){
//cout<<dis(p[i][0],p[j][0])<<endl;
G[i].push_back(j+n);
G[j].push_back(i+n);
}
if(2.0*r>dis(p[i][1],p[j][1])){
G[i+n].push_back(j);
G[j+n].push_back(i);
}
if(2.0*r>dis(p[i][0],p[j][1])){
G[i].push_back(j);
G[j+n].push_back(i+n);
}
if(2.0*r>dis(p[i][1],p[j][0])){
G[i+n].push_back(j+n);
G[j].push_back(i);
}
}
}
for(int i=1;i<=2*n;i++){
if(!dfn[i]) Tarjan(i);
}
for(int i=1;i<=n;i++){
if(color[i]==color[i+n]){
return 0;
}
}
return 1;
}
int main(){
while(scanf("%d",&n)!=EOF){
init(n);
for(int i=1;i<=n;i++){
scanf("%lf %lf %lf %lf",&p[i][0].x,&p[i][0].y,&p[i][1].x,&p[i][1].y);
}
// cout<<check(1.41)<<endl;
double l=0;double r=1e18;
for(int i=1;i<=100;i++){
double mid=(l+r)*0.5;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.2lf\n",l);
}
return 0;
}