sgu 128 分类: sgu 2015-03-13 13:56 44人阅读 评论(0) 收藏


有很多个点,最多一万个,告诉你它们的坐标。现在需要构造一条闭合线。
这个闭合线满足以下六点:
1必须是闭合的。
2必须用到所有的点。
3构造的线段之间若成角,则必须是90度。
4构造的边必须与x或y轴平行。
5构造的线段之间不存在交错和重复的情况。
6最后形成的闭合线长度必须要是所有可能中最短的。


首先根据题意处理出线段
横坐标相等的,按纵坐标从小到大排序,
第一个点与第二个点相连,第三个与第四个相连。。。
纵坐标相等的,按横坐标从小到大排序,
第一个点与第二个点相连,第三个与第四个相连。。。
O(NlogN)

最后判断连通与自交的情况,
连通用并查集O(N)
自交用暴力(^_^),O(N2),然而常数较小




#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>

const int MAXN = 10005;

int n;
int fa[MAXN] = {0};

struct node{int x,y,i;}map[MAXN] = {0} , map0[MAXN] ={0};
struct line{int i1,i2;}mpr[MAXN] = {0}, mpc[MAXN] = {0};
int rl = 0 , cl = 0;

bool cmpr(const node &a,const node &b){return ((a.y<b.y)||(a.y == b.y && a.x<b.x));}
bool cmpc(const node &a,const node &b){return ((a.x<b.x)||(a.x == b.x && a.y<b.y));}

bool row()
{
    std::sort(map + 1, map + n +1 , cmpr);

    for(int i = 2; i <= n ; i += 2)
    {
        int j = i - 1;

        if(map[i].y == map[j].y)
        {
            ++rl;
            mpr[rl].i1 = map[j].i;
            mpr[rl].i2 = map[i].i;
        }
        else return false;
    }
    return true;
}
bool col()
{
    std::sort(map + 1, map + n +1 , cmpc);

    for(int i = 2; i <= n ; i += 2)
    {
        int j = i - 1;

        if(map[i].x == map[j].x)
        {
            ++cl;
            mpc[cl].i1 = map[j].i;
            mpc[cl].i2 = map[i].i;
        }
        else return false;
    }
    return true;
}

int find_fa(int x)
{
    if(x == fa[x])return x;
    else
     { 
      fa[x] = find_fa(fa[x]);
      return fa[x];
     }
}

bool connect()
{
    for(int i = 1 ; i <= rl; i++)
    {
        int u = find_fa(mpr[i].i1) , v = find_fa(mpr[i].i2);

        fa[std::max(u,v)] = std::min(u,v);
    }
    for(int i = 1 ; i <= cl ;i++)
    {
        int u = find_fa(mpc[i].i1) , v = find_fa(mpc[i].i2);

        fa[std::max(u,v)] = std::min(u,v);
    }

    for(int i = 1; i <= n; i++)
    {
        find_fa(i);

        if(!(fa[i] == 1))return false;
    }

    return true;
}

bool crossed()
{
    for(int i = 1 ; i <= rl; i++)
      for(int j = 1 ;j <= cl ; j++)
     {
        int a = mpr[i].i1, b = mpr[i].i2, c = mpc[j].i1, d = mpc[j].i2;
          if(map0[a].x < map0[c].x && map0[d].x < map0[b].x)
             if(map0[c].y < map0[a].y && map0[b].y < map0[d].y)
               return true;
     }


    return false;
}

int count()
{
    int ret = 0;

    for(int i = 1 ; i <= rl; i++)ret += (map0[mpr[i].i2].x - map0[mpr[i].i1].x);

    for(int i = 1 ; i <= cl; i++)ret += (map0[mpc[i].i2].y - map0[mpc[i].i1].y);

    return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("sgu128.in","r",stdin);
    freopen("sgu128.out","w",stdout);
#endif

    scanf("%d",&n);

    for(int i = 1; i <= n;i++)
    {
        scanf("%d%d",&map[i].x, &map[i].y);
        map[i].i = i , fa[i] = i;
        map0[i] = map[i];
    }

    if(((n&1)==0) &&row() && col() && connect() && (!crossed()))
        printf("%d",count());
    else
        printf("0");


#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif   
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-03-13 13:56  <Dash>  阅读(130)  评论(0编辑  收藏  举报