zoukankan      html  css  js  c++  java
  • POJ2296二分2sat

    题意:
          给n个点,每个点必须在一个正方形上,可以在正方向上面边的中点或者是下面边的中点,正方形是和x,y轴平行的,而且所有的点的正方形的边长一样,并且正方形不能相互重叠(边相邻可以),问满足这个要求的正方形的最大边长是多少?


    思路:

          点的个数最少是3,所以不存在无穷大的情况,每个点的正方形有两种选择,所以是两种中选一种,每两个点中可能存在某种选择和某种选择冲突的情况,那么好办了,是不是就是夫妻参加晚会只能去一个但是一些人之间有矛盾不能同时去的变形?直接就是2-sat,至于答案是输出最大的边长,这个好办,直接二分边长,然后每一步都是2-sat判断是否可行就ok了。


    #include<stack>
    #include<stdio.h>
    #include<string.h>
    
    #define N_node 200 + 10
    #define N_edge 100000 + 100
    
    using namespace std;
    
    typedef struct
    {
        int to ,next;
    }STAR;
    
    typedef struct
    {
        double x ,y;
    }NODE;
    
    NODE node[N_node];
    STAR E1[N_edge] ,E2[N_edge];
    int list1[N_node] ,list2[N_node] ,tot;
    int Belong[N_node] ,mark[N_node] ,CNT;
    stack<int>mysk;
    
    void add(int a ,int b)
    {
        E1[++tot].to = b;
        E1[tot].next = list1[a];
        list1[a] = tot;
    
        E2[tot].to = a;
        E2[tot].next = list2[b];
        list2[b] = tot;
    }
    
    void DFS1(int s)
    {
        mark[s] = 1;
        for(int k = list1[s] ;k ;k = E1[k].next)
        {
            int to = E1[k].to;
            if(!mark[to]) DFS1(to);
        }
        mysk.push(s);
    }
    
    void DFS2(int s)
    {
        Belong[s] = CNT;
        mark[s] = 1;
        for(int k = list2[s] ;k ;k = E2[k].next)
        {
            int to = E2[k].to;
            if(!mark[to]) DFS2(to);
        }
    }
    
    double minn(double x ,double y)
    {
        return x < y ? x : y;
    }
    
    double maxx(double x ,double y)
    {
        return x > y ? x : y;
    }
    
    bool jude(NODE a ,NODE b ,double l)
    {
        double s ,x ,z ,y;
        s = minn(a.y + l ,b.y + l);
        y = minn(a.x + l ,b.x + l);
        x = maxx(a.y ,b.y);
        z = maxx(a.x ,b.x);
        return s > x && y > z;
    
    }
    
    bool J(int n ,int nowl)
    {
        int i ,j ,a1 ,a2 ,b1 ,b2;
        NODE t1 ,t2;
        double r = nowl * 1.0 / 2;
        memset(list1 ,0 ,sizeof(list1));
        memset(list2 ,0 ,sizeof(list2));
        tot = 1;
        for(i = 1 ;i <= n ;i ++)
        for(j = i + 1 ;j <= n ;j ++)
        {
            a1 = i * 2 ,b1 = i * 2 + 1;
            a2 = j * 2 ,b2 = j * 2 + 1;
    
            //上上
            t1.x = node[i].x - r ,t1.y = node[i].y;
            t2.x = node[j].x - r ,t2.y = node[j].y;
            if(jude(t1 ,t2 ,nowl * 1.0)) add(a1 ,a2 ^ 1) ,add(a2 ,a1 ^ 1);
            //上下
            t1.x = node[i].x - r ,t1.y = node[i].y;
            t2.x = node[j].x - r ,t2.y = node[j].y - r * 2;
            if(jude(t1 ,t2 ,nowl * 1.0)) add(a1 ,b2 ^ 1) ,add(b2 ,a1 ^ 1);
            //下上
            t1.x = node[i].x - r ,t1.y = node[i].y - r * 2;
            t2.x = node[j].x - r ,t2.y = node[j].y;
            if(jude(t1 ,t2 ,nowl * 1.0)) add(b1 ,a2 ^ 1) ,add(a2 ,b1 ^ 1);
            //下下
            t1.x = node[i].x - r ,t1.y = node[i].y - r * 2;
            t2.x = node[j].x - r ,t2.y = node[j].y - r * 2;
            if(jude(t1 ,t2 ,nowl * 1.0)) add(b1 ,b2 ^ 1) ,add(b2 ,b1 ^ 1);
        }
        memset(mark ,0 ,sizeof(mark));
        while(!mysk.empty()) mysk.pop();
        n *= 2;
        for(i = 1 ;i <= n ;i ++)
        if(!mark[i]) DFS1(i);
        CNT = 0;
        memset(mark ,0 ,sizeof(mark));
        while(!mysk.empty())
        {
            int xin = mysk.top();
            mysk.pop();
            if(mark[xin]) continue;
            CNT ++;
            DFS2(xin);
        }
        int mk = 0;
        for(i = 1 ;i <= n ;i += 2)
        if(Belong[i] == Belong[i^1])
        {
            mk = 1;
            break;
        }
        return !mk;
    }
    
    int main ()
    {
        int t ,n ,i ,j;
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d" ,&n);
            for(i = 1 ;i <= n ;i ++)
            scanf("%lf %lf" ,&node[i].x ,&node[i].y);
            int low = 0 ,up = 20000 + 100 ,mid ,ans = 0;
            while(low <= up)
            {
                mid = (low + up) >> 1;
                if(J(n ,mid)) ans = mid ,low = mid + 1;
                else up = mid - 1;
            }
            printf("%d
    " ,ans);
        }
        return 0;
    }
    
    
    
    
    


  • 相关阅读:
    物联网数据卡系统源码——物联网的主要应用领域
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    memcached对key和value的限制 memcached的key最大长度和Value最大长度
    缓存技术PK:选择Memcached还是Redis?
    .Net开源框架列表
    项目管理工具Redmine各功能测试
    DBImport V3.7版本发布及软件稳定性(自动退出问题)解决过程分享
    ASP.NET Core 折腾笔记一
    发布:.NET开发人员必备的可视化调试工具(你值的拥有)
    开源发布:VS代码段快捷方式及可视化调试快速部署工具
  • 原文地址:https://www.cnblogs.com/csnd/p/12062388.html
Copyright © 2011-2022 走看看