POJ 3293 Rectilinear polygon(几何基础)

 

【题目链接】 http://poj.org/problem?id=3293

 

【题目大意】

  给出一些点,每个点只能向外引出一条平行X轴,和Y轴的边,
  问能否构成一个闭多边形,如果能,返回多边形的总边长,否则返回-1

 

【题解】

  我们发现对于每一行或者每一列都必须有偶数个点,且两两之间相邻才能满足条件
  所以我们将其连线之后判断是否可以构成一个封闭图形,同时还需要判断这些线是否会相交,
  如果相交即不成立

 

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=100010; 
struct Point{int x,y,id;}p[N];
struct Line{
    int d,x,y;
    Line(){}
    Line(int _d,int _x,int _y):d(_d),x(_x),y(_y){}
}l[N];
int cmp_x(Point a,Point b){
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
int cmp_y(Point a,Point b){
    if(a.y==b.y)return a.x<b.x;
    return a.y<b.y;
}
int con[N][2],n,ln,T;
int Check(Point a,Point b){
    int y=a.y,x1=a.x,x2=b.x;
    for(int i=0;i<ln;i++){
        if(x1<l[i].d&&x2>l[i].d&&l[i].x<y&&l[i].y>y)return 1;
    }return 0;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            p[i].id=i;
        }int s=0,cnt=1,flag=0;
        ln=0;
        sort(p,p+n,cmp_x);
        for(int i=1;i<n&&!flag;i++){
            if(p[i].x!=p[i-1].x){
                if(cnt&1)flag=1;
                cnt=1;
            }else{
                cnt++;
                if((cnt&1)==0){
                    s+=p[i].y-p[i-1].y;
                    con[p[i].id][0]=p[i-1].id;
                    con[p[i-1].id][0]=p[i].id;
                    l[ln++]=Line(p[i].x,p[i-1].y,p[i].y);
                }
            }
        }sort(p,p+n,cmp_y);
        cnt=1;
        for(int i=1;i<n&&!flag;i++){
            if(p[i].y!=p[i-1].y){
                if(cnt&1)flag=1;
                cnt=1;
            }
            else{
                cnt++;
                if((cnt&1)==0){
                    s+=p[i].x-p[i-1].x;
                    con[p[i].id][1]=p[i-1].id;
                    con[p[i-1].id][1]=p[i].id;
                    if(Check(p[i-1],p[i]))flag=1;
                }
            }
        }int t=1,x=0,c=0;
        for(;;){
            x=con[x][t];
            t^=1; c++;
            if(x==0||flag)break;
        }if(c!=n)flag=1;
        if(flag)puts("-1");
        else printf("%d\n",s);
    }return 0;
}

转载于:https://www.cnblogs.com/forever97/p/poj3293.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值