zoukankan      html  css  js  c++  java
  • 【HDU3622】Bomb Game-二分答案+2-SAT

    测试地址:Bomb Game
    题目大意:n组点,每组有两个点,要从每组点中选择一个放置炸弹,每个炸弹的爆炸范围是一个以炸弹为圆心的圆,每个圆的半径都可以调整,要求所有圆都不相交,求所有圆中最小半径的最大值,精确到两位小数。
    做法:本题需要用到二分答案+2-SAT。
    首先,看到求最小的啥啥啥的最大值就想到二分答案。因为对于一个可行解,把任何圆的半径减小,也是一个可行解,因此所有可行解都等价于所有圆半径相同的一个解,所以如果所有圆半径为r时满足条件,那么半径<r时也满足条件,满足可二分性。那么我们只需二分所有圆的共同半径,问题转化为判定性问题。
    注意到题目中的“两个中只能选一个”的条件,很显然就是2-SAT的模型,那么考虑限制条件:任两个圆不相交。我们知道两个圆相交的条件是r1+r2>dis(O1,O2),那么我们可以根据这个条件求出两个圆是否相交,如果相交的话,那么这两个圆不能同时被选。这个限制就很容易转化到2-SAT模型中了,建图后就可以判断有没有可行解了。结合二分答案就解决了此题,总时间复杂度为O(n2log)
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #define eps 1e-8
    using namespace std;
    int n;
    double x[210],y[210],dis[210][210];
    int belong[210],stack[210],first[210],top,tott,tot,tim;
    int dfn[210],low[210];
    bool vis[210];
    struct edge {int v,next;} e[100010];
    
    void insert(int a,int b)
    {
        e[++tot].v=b;
        e[tot].next=first[a];
        first[a]=tot;
    }
    
    int nt(int x)
    {
        if (x%2==0) return x+1;
        else return x-1;
    }
    
    void dfs(int v)
    {
        vis[v]=1;
        dfn[v]=low[v]=++tim;
        stack[++top]=v;
        int now=top;
        for(int i=first[v];i;i=e[i].next)
        {
            if (!vis[e[i].v])
            {
                dfs(e[i].v);
                low[v]=min(low[v],low[e[i].v]);
            }
            else if (!belong[e[i].v]) low[v]=min(low[v],dfn[e[i].v]);
        }
        if (low[v]==dfn[v])
        {
            tott++;
            for(int i=now;i<=top;i++)
                belong[stack[i]]=tott;
            top=now-1;
        }
    }
    
    void tarjan()
    {
        memset(vis,0,sizeof(vis));
        memset(belong,0,sizeof(belong));
        tim=0;
        for(int i=0;i<2*n;i++)
            if (!vis[i]) dfs(i);
        tott++;
        for(int i=1;i<=top;i++)
            belong[stack[i]]=tott;
    }
    
    bool check(double r)
    {
        memset(first,0,sizeof(first));
        top=tot=tott=0;
    
        for(int i=0;i<2*n;i++)
            for(int j=i+1;j<2*n;j++)
                if (dis[i][j]-r*2<-eps)
                {
                    insert(i,nt(j));
                    insert(j,nt(i));
                }
    
        tarjan();
    
        for(int i=0;i<n;i++)
            if (belong[2*i]==belong[2*i+1]) return 0;
        return 1;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=0;i<2*n;i++)
                scanf("%lf%lf",&x[i],&y[i]);
            for(int i=0;i<2*n;i++)
                for(int j=i+1;j<2*n;j++)
                    dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
    
            double l=0,r=40000;
            while(r-l>0.0001)
            {
                double mid=(l+r)/2.0;
                if (check(mid)) l=mid;
                else r=mid;
            }
    
            printf("%.2lf
    ",l);
        }
    
        return 0;
    }
    
  • 相关阅读:
    toj 2975 Encription
    poj 1797 Heavy Transportation
    toj 2971 Rotating Numbers
    zoj 2281 Way to Freedom
    toj 2483 Nasty Hacks
    toj 2972 MOVING DHAKA
    toj 2696 Collecting Beepers
    toj 2970 Hackle Number
    toj 2485 Card Tric
    js页面定位,相关几个属性
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793618.html
Copyright © 2011-2022 走看看