Connected?(STL瞎搞)

12 篇文章 0 订阅

                                            Connected?

                                                                   时间限制: 1 Sec  内存限制: 128 MB
                                                                                提交: 40  解决: 21
                                                                   [提交] [状态] [讨论版] [命题人:admin]

题目描述

Snuke is playing a puzzle game. In this game, you are given a rectangular board of dimensions R×C, filled with numbers. Each integer i from 1 through N is written twice, at the coordinates (xi,1,yi,1) and (xi,2,yi,2).
The objective is to draw a curve connecting the pair of points where the same integer is written, for every integer from 1 through N. Here, the curves may not go outside the board or cross each other.
Determine whether this is possible.

Constraints
1≤R,C≤108
1≤N≤105
0≤xi,1,xi,2≤R(1≤i≤N)
0≤yi,1,yi,2≤C(1≤i≤N)
All given points are distinct.
All input values are integers.

输入

Input is given from Standard Input in the following format:
R C N
x1,1 y1,1 x1,2 y1,2
:
xN,1 yN,1 xN,2 yN,2

输出

Print YES if the objective is achievable; print NO otherwise.

样例输入

4 2 3
0 1 3 1
1 1 4 1
2 0 2 2

样例输出

YES

提示


The above figure shows a possible solution.

                                                                                  [提交]       [状态]

题意:判断是否可以在图内连线使相同数字连接起来且连线不交叉。

题解:想了半天考虑什么情况下会出现交叉现象,作图可以发现只要不是两个点都位于矩形边界之上,都一定可以通过各种神奇的扭曲实现连接(总有缝可以钻:)。所以排除所有两点不同时在矩形边界的线段,剩下的只需要保证两点都在边界的线段不相交即可,官方题解用了栈处理,按顺时针排序所有线段(每个点到原点的距离)后(线段两点也按顺时针方向排序),按顺时针遍历每个点,如果是线段起始点,push这个点对应的终止点。如果是线段终止点,检查栈顶是否是这个点,如果不是则当前点线段则和应该出现的点的线段一定相交,具体看代码。

右图遍历到A‘时栈顶应该为B‘,所以不成立。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <vector>
#include<stack>
#include<numeric>
using namespace std;

int R,C,N;
struct node{
    int u;
    int v;
    int flag;
}no[200005];
bool cmp(node a,node b)
{
    return a.u < b.u;
}
int Change(int x, int y)//返回的是当前这个点到原点的距离(顺时针)
{
    if (x == 0)
        return y;
    else if (y == C)
        return C + x;
    else if (x == R)
        return R + C + C - y;
    else if (y == 0)
        return R+R+C+C-x;
    else
        return -1;
}
int main()
{
    int cnt=0;
    scanf("%d%d%d",&R,&C,&N);
    for(int i=0;i<N;i++)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        int flag1=Change(a,b);
        int flag2=Change(c,d);
        if(flag1 == -1 || flag2 == -1)
            continue;
        if(flag1 > flag2)//保证距离小的在前面(顺时针)
            swap(flag1,flag2);
        no[cnt].flag=1;
        no[cnt].u=flag1;
        no[cnt++].v=flag2;
        no[cnt].flag=2;
        no[cnt].u=flag2;
        no[cnt++].v=flag1;
    }
    stack<int>S;
    sort(no,no+cnt,cmp);
    for(int i=0;i<cnt;i++)
    {
        if(no[i].flag==1)
            S.push(no[i].v);
        else if(S.top()==no[i].u)
            S.pop();
        else
        {
            printf("NO\n");
            return 0;
        }
    }
    printf("YES\n");
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值