1. 程式人生 > >HDU 3622 Bomb Game

HDU 3622 Bomb Game

題意:給你n個炸彈,每個炸彈都有兩個位置放置,問你最大的爆炸半徑,使得任意兩個炸彈的爆炸範圍不相交,可以相切,問半徑是多少

思路:對半徑進行二分,很顯然是單調的,所以滿足條件,然後由於點數不是很多,每次n2暴力建圖跑sat

程式碼:(忘記跑tarjan對著空氣debug半小時)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1005;
const int maxm=2000005;
const double eps=1e-4;

struct point
{
    double x,y;
}p[
1005]; struct node { int to,nxt; } edge[maxm]; int head[maxn]; int low[maxn],dfn[maxn],stk[maxn],be[maxn]; int top,tim,num,tot;/// init -1 0 0 0 bool instk[maxn]; void add_edge(int u,int v) { edge[tot].to=v; edge[tot].nxt=head[u]; head[u]=tot++; } void init() { tot=0;num=0
;tim=0; top=-1; memset(dfn,0,sizeof(dfn)); memset(head,-1,sizeof(head)); memset(instk,false,sizeof(instk)); } void tarjan(int u) { int v; low[u]=dfn[u]=++tim; stk[++top]=u; instk[u]=1; for(int k=head[u];~k;k=edge[k].nxt){ v=edge[k].to;
if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(instk[v]){ low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ ++num; do{ v=stk[top--]; instk[v]=false; be[v]=num; } while(u!=v); } } double dist(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int n; void build(double x) { // printf("asd %d\n",n*2); for(int i=0;i<2*n;i++){ for(int j=0;j<2*n;j++){ if((i/2!=j/2)&&(dist(p[i],p[j])<x)){ add_edge(i,j^1); add_edge(j,i^1); // printf("fuck %d %d %d %d\n",i,j^1,j,i^1); } } } } bool check(double x) { init(); build(x*2.0); for(int i=0;i<2*n;i++){ if(!dfn[i])tarjan(i); } bool ok=true; for(int i=0;i<2*n;i+=2){ if(be[i]==be[i^1]){ ok=false;break; } } return ok; } int main() { while(~scanf("%d",&n)){ for(int i=0;i<n;i++){ scanf("%lf%lf%lf%lf",&p[i*2].x,&p[i*2].y,&p[i*2+1].x,&p[i*2+1].y); } // printf("test %d\n",check(1.0)); double L=0.0,R=9999999.0; while(L+eps<R){ double mid=(L+R)*0.5; if(check(mid)){ L=mid; } else R=mid; } printf("%.2f\n",L); } return 0; }