poj2296

Map generation is a difficult task in cartography. A vital part of such task is automatic labeling of the cities in a map; where for each city there is text label to be attached to its location, so that no two labels overlap. In this problem, we are concerned with a simple case of automatic map labeling. 

Assume that each city is a point on the plane, and its label is a text bounded in a square with edges parallel to x and y axis. The label of each city should be located such that the city point appears exactly in the middle of the top or bottom edges of the label. In a good labeling, the square labels are all of the same size, and no two labels overlap, although they may share one edge. Figure 1 depicts an example of a good labeling (the texts of the labels are not shown.) 

Given the coordinates of all city points on the map as integer values, you are to find the maximum label size (an integer value) such that a good labeling exists for the map. 

Input

The first line contains a single integer t (1 <= t <= 10), the number of test cases. Each test case starts with a line containing an integer m (3 ≤ m ≤ 100), the number of cities followed by m lines of data each containing a pair of integers; the first integer (X) is the x and the second one (Y) is the y coordinates of one city on the map (-10000 ≤X, Y≤ 10000). Note that no two cities have the same (x, y) coordinates.

Output

The output will be one line per each test case containing the maximum possible label size (an integer value) for a good labeling.

Sample Input

1
6
1 1
2 3
3 2
4 4
10 4
2 5

Sample Output

2

题意:

        平面上有n个给定坐标且不重叠的点,现在每个点要画一个大小相同的正方形(各边平行于坐标轴),对于每个点来说,该点只能在该正方形的上边的中点或下边的中点.现在的问题是,该正方形最大边长能为多少(整数),且各个点的正方形还能不重叠?

分析:

        其实每个点只有两种选择,朝上画或者朝下画.对于任意两个点a和b来说,假设a=0表示朝上画,a=1表示朝下画.那么如果对于固定正方形长度mid来说, a朝上且b朝上时,正方形如果重叠,那么可以推出边: a = 0 -> b=1 且b=0 -> a=1. 依次类推.

        假设点都存在结构体s[n]中,如果abs(s[i].x-s[j].x)>= mid ,则可以随便放.(i取0表示上放,i取1表示下放)

        否则abs(s[i].x-s[j].x)<mid时:

        1.abs(s[i].y-s[j].y)==0,则必须一个放上,一个放下. add(i,0,j,1) add(i,1,j,0), add(j,0,i,1), add(j,1,i,0)

        2.0<abs(s[i].y-s[j].y)<mid, 则必须上面的点上放,下面的点下放. 假设i点在上,j点在下(即 s[i].y > s[j].y) ,则add(i,1,i,0) 且add(j,0,j,1)

        3.mid<=abs(s[i].y-s[j].y)<2*mid,则只有一种情况不合法,即上面的点往下放且下面的点往上放. 假设i点在上,则:

add(i,1,j,1) 且 add(j,0,i,0)
代码:
 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
const int maxn=100000+10;
int n;
struct dian
{
    int x,y;
    dian(){}
    dian(int x,int y):x(x),y(y){}
}di[maxn];
struct TwoSAT
{
    int n;
    vector<int> G[maxn*5];
    int S[maxn*5],c;
    bool mark[maxn*2];
    bool dfs(int x)
    {
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x]=true;
        S[c++]=x;
        for(int i=0;i<G[x].size();i++)
            if(!dfs(G[x][i])) return false;
        return true;
    }

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<n*2;i++) G[i].clear();
        memset(mark,0,sizeof(mark));
    }

    void add_clause(int x,int xval,int y,int yval)//这里的函数做了修改,只加单向边
    {
        x=x*2+xval;
        y=y*2+yval;
        G[x].push_back(y);
    }

    bool solve()
    {
        for(int i=0;i<2*n;i+=2)
        if(!mark[i] && !mark[i+1])
        {
            c=0;
            if(!dfs(i))
            {
                while(c>0) mark[S[--c]]=false;
                if(!dfs(i+1)) return false;
            }
        }
        return true;
    }
}TT;
bool ss(int mid)
{
    TT.init(n);
    for(int i=0;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(abs(di[i].x-di[j].x)<mid)
            {
                if(di[i].y==di[j].y)
                {
                    TT.add_clause(i,0,j,1);
                    TT.add_clause(i,1,j,0);
                    TT.add_clause(j,0,i,1);
                    TT.add_clause(j,1,i,0);
                }
                else if(abs(di[i].y-di[j].y)<mid)
                {
                    if(di[i].y>di[j].y)
                    {
                        TT.add_clause(i,1,i,0);
                        TT.add_clause(j,0,j,1);
                        TT.add_clause(i,0,j,1);
                        TT.add_clause(j,1,i,0);
                    }
                    if(di[i].y<di[j].y)
                    {
                         TT.add_clause(j,1,j,0);
                         TT.add_clause(i,0,i,1);
                        TT.add_clause(i,1,j,0);
                        TT.add_clause(j,0,i,1);
                    }
                }
                else if(abs(di[i].y-di[j].y)<2*mid)
                {
                        
                        if(di[i].y>di[j].y)
                        {
                            TT.add_clause(i,1,j,1);
                            TT.add_clause(j,0,i,0);
                        }
                        if(di[i].y<di[j].y)
                        {
                            TT.add_clause(j,1,i,1);
                            TT.add_clause(i,0,j,0);
                        }
                }
            }
        }
    }
    return TT.solve();
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        {
            for(int i=0;i<n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                di[i]=dian(x,y);
            }
        }
        int L=0,R=20000+1;
        while(R>L)
        {
            int mid = L+(R-L+1)/2;
            if(ss(mid)) L=mid;
            else R=mid-1;
        }
        printf("%d\n",L);

    }
}

猜你喜欢

转载自blog.csdn.net/qq_40859951/article/details/88085897
今日推荐