zoukankan      html  css  js  c++  java
  • AtCoder ARC 076E

    传送门:http://arc076.contest.atcoder.jp/tasks/arc076_c

    平面上有一个R×C的网格,格点上可能写有数字1~N,每个数字出现两次。现在用一条曲线将一对相同的数字连接,对于数字1~N。试判断是否存在一种连接方式,使得曲线不越过矩形网格边界,且曲线之间不相交?

    若平面网格为无限大,则使得曲线之间不相交的连接方式一定存在。因此,在一个R×C的网格上,优先考虑边界上的点对,再考虑不全在边界上的点对。将两次均处于边界上的数字的集合记为S

    由于曲线不越过网格边界,因此规定曲线均位于边界内侧。以下只需考虑曲线是否相交。

    设集合S中的元素i,j,在边界上出现的顺序为i,j,i,j,则连接i点对的曲线与连接j点对的曲线一定相交;若出现的顺序为i,i,j,ji,j,j,i,则连接i点对的曲线与连接j点对的曲线不相交。因此,可以考虑用栈(Stack)实现边界点对的检验:沿顺时针方向遍历边界上的点对,若当前栈不为空,且栈顶元素与当前位置的数字相同,则将栈顶元素弹出;否则将当前位置的数字压入栈。如此,若最终栈为空,则答案为YES,否则为NO。

    参考程序如下:

    #include <bits/stdc++.h>
    using namespace std;
    
    #define MAX_N 100010
    
    int r, c, n;
    stack<int> s;
    struct point {int id, coor;} p[4][2 * MAX_N];
    
    int boundary(int x, int y)
    {
        if (x == 0) return 0;
        else if (y == c) return 1;
        else if (x == r) return 2;
        else if (y == 0) return 3;
        else return -1;
    }
    
    bool cmp_inc(point a, point b)
    {
        return a.coor < b.coor;
    }
    
    bool cmp_dec(point a, point b)
    {
        return a.coor > b.coor;
    }
    
    int main(void)
    {
        scanf("%d%d%d", &r, &c, &n);
        int cnt[4] = {0};
        for (int i = 1; i <= n; i++) {
            int x[2], y[2];
            scanf("%d%d%d%d", &x[0], &y[0], &x[1], &y[1]);
            bool is_boundary = true;
            for (int j = 0; j < 2; j++) {
                if (x[j] % r && y[j] % c) is_boundary = false;
            }
            if (is_boundary) {
                for (int j = 0; j < 2; j++) {
                    int t = boundary(x[j], y[j]);
                    p[t][cnt[t]].id = i;
                    p[t][cnt[t]].coor = t % 2? x[j]: y[j];
                    cnt[t]++;
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            if (i < 2) sort(p[i], p[i] + cnt[i], cmp_inc);
            else sort(p[i], p[i] + cnt[i], cmp_dec);
            for (int j = 0; j < cnt[i]; j++) {
                if (s.size() && s.top() == p[i][j].id)
                    s.pop();
                else
                    s.push(p[i][j].id);
            }
        }
        if (s.empty()) printf("YES
    ");
        else printf("NO
    ");
        return 0;
    }
  • 相关阅读:
    NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)
    NOIp2018D1T1 积木大赛 【思维】
    NOIp2018D1T2 货币系统【分析&完全背包】
    NOIp2017D1T2 时间复杂度【模拟】
    NOIp2015D1T3 斗地主【暴搜】
    NOIp2013D2T3 华容道【搜索&图论-最短路】
    Andrew算法求二维凸包-学习笔记
    最小割的一些小技巧(实用小干货)
    USACO4.3 Buy Low, Buy Lower【简单dp·高精度】
    iOS本地推送与远程推送详解
  • 原文地址:https://www.cnblogs.com/siuginhung/p/7751330.html
Copyright © 2011-2022 走看看