POJ 2296 Map Labeler

二分答案 + 2-SAT验证,判断正方形是否相交写起来有点烦,思路还是挺简单的。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=1005;
struct Point
{
    double x,y;
}p[maxn];
int N;

stack<int>S;
vector<int>G[maxn];
vector<int>FG[maxn];
int Belong[maxn];
int flag[maxn];
int Block;

int left,right,mid,ans;

void init()
{
    for(int i=0; i<maxn; i++) G[i].clear();
    for(int i=0; i<maxn; i++) FG[i].clear();
    memset(Belong,0,sizeof Belong);
    memset(flag,0,sizeof flag);
    while(!S.empty()) S.pop();
    Block=0;
}

void addEdge(int x,int y)
{
    G[x].push_back(y);
    FG[y].push_back(x);
}

void dfs1(int now)
{
    flag[now]=1;
    for(int i=0; i<G[now].size(); i++)
        if(!flag[G[now][i]])
            dfs1(G[now][i]);
    S.push(now);
}

void dfs2(int now)
{
    Belong[now]=Block;
    for(int i=0; i<FG[now].size(); i++)
        if(!Belong[FG[now][i]])
            dfs2(FG[now][i]);
}

bool judge()
{
    for(int i=0; i<2*N; i++) if(!flag[i]) dfs1(i);
    while(!S.empty())
    {
        int Top=S.top();
        S.pop();
        if(!Belong[Top])
        {
            Block++;
            dfs2(Top);
        }
    }
    for(int i=0; i<N; i++)
        if(Belong[2*i]==Belong[2*i+1])
            return 0;
    return 1;
}

bool F(int p1,int p2,int f1,int f2)
{
    double leftTop_p1_x,leftTop_p1_y;
    double rightBottom_p1_x,rightBottom_p1_y;

    double leftTop_p2_x,leftTop_p2_y;
    double rightBottom_p2_x,rightBottom_p2_y;

    if(f1==0)
    {
        leftTop_p1_x=p[p1].x-1.0*mid/2;
        leftTop_p1_y=p[p1].y;

        rightBottom_p1_x=p[p1].x+1.0*mid/2;
        rightBottom_p1_y=p[p1].y-mid;
    }
    else
    {
        leftTop_p1_x=p[p1].x-1.0*mid/2;
        leftTop_p1_y=p[p1].y+mid;

        rightBottom_p1_x=p[p1].x+1.0*mid/2;
        rightBottom_p1_y=p[p1].y;
    }

    if(f2==0)
    {
        leftTop_p2_x=p[p2].x-1.0*mid/2;
        leftTop_p2_y=p[p2].y;

        rightBottom_p2_x=p[p2].x+1.0*mid/2;
        rightBottom_p2_y=p[p2].y-mid;
    }

    else
    {
        leftTop_p2_x=p[p2].x-1.0*mid/2;
        leftTop_p2_y=p[p2].y+mid;

        rightBottom_p2_x=p[p2].x+1.0*mid/2;
        rightBottom_p2_y=p[p2].y;
    }

    if(leftTop_p1_x<leftTop_p2_x&&leftTop_p2_x<rightBottom_p1_x
        && rightBottom_p1_y<leftTop_p2_y&&leftTop_p2_y<leftTop_p1_y) return 1;

    if(leftTop_p1_x<leftTop_p2_x&&leftTop_p2_x<rightBottom_p1_x
        && rightBottom_p1_y<rightBottom_p2_y&&rightBottom_p2_y<leftTop_p1_y) return 1;

    if(leftTop_p1_x<rightBottom_p2_x&&rightBottom_p2_x<rightBottom_p1_x
        && rightBottom_p1_y<leftTop_p2_y&&leftTop_p2_y<leftTop_p1_y) return 1;

    if(leftTop_p1_x<rightBottom_p2_x&&rightBottom_p2_x<rightBottom_p1_x
        && rightBottom_p1_y<rightBottom_p2_y&&rightBottom_p2_y<leftTop_p1_y) return 1;

    if(leftTop_p2_x<leftTop_p1_x&&leftTop_p1_x<rightBottom_p2_x
        && rightBottom_p2_y<leftTop_p1_y&&leftTop_p1_y<leftTop_p2_y) return 1;

    if(leftTop_p2_x<leftTop_p1_x&&leftTop_p1_x<rightBottom_p2_x
        && rightBottom_p2_y<rightBottom_p1_y&&rightBottom_p1_y<leftTop_p2_y) return 1;

    if(leftTop_p2_x<rightBottom_p1_x&&rightBottom_p1_x<rightBottom_p2_x
        && rightBottom_p2_y<leftTop_p1_y&&leftTop_p1_y<leftTop_p2_y) return 1;

    if(leftTop_p2_x<rightBottom_p1_x&&rightBottom_p1_x<rightBottom_p2_x
        && rightBottom_p2_y<rightBottom_p1_y&&rightBottom_p1_y<leftTop_p2_y) return 1;

    if(leftTop_p1_x==leftTop_p2_x&&rightBottom_p1_x==rightBottom_p2_x)
    {
        if(rightBottom_p1_y<leftTop_p2_y&&leftTop_p2_y<leftTop_p1_y) return 1;
        if(rightBottom_p1_y<rightBottom_p2_y&&rightBottom_p2_y<leftTop_p1_y) return 1;

        if(rightBottom_p2_y<leftTop_p1_y&&leftTop_p1_y<leftTop_p2_y) return 1;
        if(rightBottom_p2_y<rightBottom_p1_y&&rightBottom_p1_y<leftTop_p2_y) return 1;
    }

    if(leftTop_p1_y==leftTop_p2_y&&rightBottom_p1_y==rightBottom_p2_y)
    {
        if(leftTop_p1_x<leftTop_p2_x&&leftTop_p2_x<rightBottom_p1_x) return 1;
        if(leftTop_p1_x<rightBottom_p2_x&&rightBottom_p2_x<rightBottom_p1_x) return 1;

        if(leftTop_p2_x<leftTop_p1_x&&leftTop_p1_x<rightBottom_p2_x) return 1;
        if(leftTop_p2_x<rightBottom_p1_x&&rightBottom_p1_x<rightBottom_p2_x) return 1;
    }

    if(leftTop_p1_x==leftTop_p2_x&&rightBottom_p1_x==rightBottom_p2_x)
        if(leftTop_p1_y==leftTop_p2_y&&rightBottom_p1_y==rightBottom_p2_y)
            return 1;

    return 0;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        for(int i=0;i<N;i++) scanf("%lf%lf",&p[i].x,&p[i].y);

        left=0;right=50000;
        while(left<=right)
        {
            mid=(left+right)/2;
            init();
            for(int i=0;i<N;i++)
            {
                for(int j=i+1;j<N;j++)
                {
                    if(F(i,j,0,0)) {addEdge(2*i,2*j+1);addEdge(2*j,2*i+1);}
                    if(F(i,j,0,1)) {addEdge(2*i,2*j);addEdge(2*j+1,2*i+1);}
                    if(F(i,j,1,0)) {addEdge(2*i+1,2*j+1);addEdge(2*j,2*i);}
                    if(F(i,j,1,1)) {addEdge(2*i+1,2*j);addEdge(2*j+1,2*i);}
                }
            }
            if(judge()) {ans=mid;left=mid+1;}
            else right=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-10 23:45:18

POJ 2296 Map Labeler的相关文章

POJ 2296 Map Labeler(2-sat)

POJ 2296 Map Labeler 题目链接 题意: 坐标轴上有N个点,要在每个点上贴一个正方形,这个正方形的横竖边分别和x,y轴平行,并且要使得点要么在正方形的上面那条边的中点,或者在下面那条边的中点,并且任意两个点的正方形都不重叠(可以重边).问正方形最大边长可以多少? 思路:显然的2-sat问题,注意判断两个矩形相交的地方,细节 代码: #include <cstdio> #include <cstring> #include <cstdlib> #incl

poj 2296 Map Labeler【二分+2-set】【经典】

题目:poj 2296 Map Labeler 题意:给出以下二维坐标点,然后让你往平面上放正方形,点必须落在正方形上面边的中点或者下面边的中点,正方形不能重叠,可以共用边.问最大正方形边的边长. 分析:这种最大化最小值或者最小化最大值的问题,我们都可以种二分+判断的方法来解,这个也不例外,关键是判断部分 我们现在二分枚举边长为diff,然后所有的点就变成了在正方形上面或者下面的问题了,二选一的问题很明显可以用2-set来判断的 这个题目的关键在于理解他们之间的二元关系并建图,下面我们来分析 首

POJ 2296 Map Labeler(二分边长+2-sat判解)(经典题)

题意:给你n个点,要你在这n个点上放一个正方形,点只能在正方形的上边或下边的中点上,所有正方形大小一样, 不能重叠,求最大的正方形. 经典的题目,找约束关系要经过一些讨论. //320 KB 16 ms #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 222; int n; struct n

Map Labeler (poj 2296 二分+2-SAT)

Language: Default Map Labeler Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1815   Accepted: 599 Description Map generation is a difficult task in cartography. A vital part of such task is automatic labeling of the cities in a map; whe

POJ2296 Map Labeler【2-SAT】【二分】

题目链接: http://poj.org/problem?id=2296 题目大意: 制作地图是一件很复杂的工作,其中一项任务就是为地图上的城市制作标示--在地图上每个 城市的所在位置附近贴上一个文字标签.标签的一个要求就是亮亮不能重叠.本题中,假设每 个城市都是平面上的一个点,坐标为(x,y),他的标签是一个平行于xy轴的正方形,现在要求 代表每个城市的点处于正方形标签的顶边正中央或是底边正中央,如下图所示.对于一个好的 地图,所有的标签大小都应该相同,并且任意两个标签之间没有重叠,但是可以有

POJ 2503-Babelfish(map)

题目地址:POJ 2503 题意:输入一个字典,字典格式为"英语 外语"的一一映射关系然后输入若干个外语单词,输出他们的 英语翻译单词,如果字典中不存在这个单词,则输出"eh". 思路:用map存取外语和英语的映射关系,然后找就好了.注意输入格式. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include

POJ2296.Map Labeler——2-sat二分最大值+可行性判断

http://poj.org/problem?id=2296 题目描述: 在二维坐标在有n个点,在这n个点上放正方形,每个点只能放在正方形上/下边界的中点,要使得这n个点放置的正方形互不相交,求正方形的最大边长 分析: 每个正方形要么放上面,要么放下面,2种限制... 对第i个点,2*i表示放上面,2*i+1表示放下面.设边长为r 1.当abs(x[i]-x[j])>=r,则这两个正方形可以任意放 2.当abs(y[i]-y[j]) < r 2.1当y[i]==y[j]时,i和j的放法相反 i

POJ 2296 二分+2-sat

题目大意: 给定n个点,给每个点都安排一个相同的正方形,使这个点落在正方形的下底边的中间或者上底边的中间,并让这n个正方形不出现相互覆盖,可以共享同一条边,求 这个正方形最大的边长 这里明显看出n个点,每个点都只有在上底边和下底边两种选择,所以这里是2-sat解决 这里全都是整数,而因为点在正方形的中间,所以/2后会有小数 我这里初始将所有点都扩大两倍,那么答案必然扩大两倍,所以我们二分只考虑边长为偶数的情况即可,这样计算结果就不会出现小数了 最后将答案除以2便是 1 #include <cst

【图论】2-sat总结

2-sat总结 2-sat问题,一般表现的形式为.每一个点有两种方式a,b,要么选a,要么选b.而且点点之间有一些约束关系.比如:u和v至少一个选a.那么这就是一个表达式.把a当成真,b当成假,那就是u真或v真.2-sat的题目就是这样.给定这些约束,推断是否会矛盾 注意表达式的转化形式,(事实上就是离散数学中那几种转换方式) 比方(u真且v真)或(u假且v假)就能够转化成(u真或v假)且(u假或v真),这样就能建立关系 2-sat中的原理,事实上和2染色是一样的,把每一个结点拆分成一个真结点和