1 条题解

  • 0
    @ 2026-4-1 18:38:18

    题意简述

    你位于无限笛卡尔平面上的点 (0,0)(0,0)。你有一个带有 44 个按钮的控制器,每个按钮可以执行以下操作之一:

    • UU:从 (x,y)(x,y) 移动到 (x,y+1)(x,y+1)
    • RR:从 (x,y)(x,y) 移动到 (x+1,y)(x+1,y)
    • DD:从 (x,y)(x,y) 移动到 (x,y1)(x,y-1)
    • LL:从 (x,y)(x,y) 移动到 (x1,y)(x-1,y)

    不幸的是,控制器坏了。如果你按下了全部 44 个按钮(无论顺序如何),控制器就会停止工作。这意味着在整个行程中,你最多只能按 33 个不同的按钮(每个按钮可以按任意次数,顺序任意)。

    平面上有 nn 个特殊点,坐标为整数 (xi,yi)(x_i, y_i)。你能否在不损坏控制器的情况下访问所有特殊点(顺序任意)?


    解法分析

    关键观察

    • 如果只使用 U,R,DU,R,D 三个按钮,则 xx 坐标永远不会减少,因此只能到达 x0x \ge 0 的区域。
    • 如果只使用 U,R,LU,R,L 三个按钮,则 yy 坐标永远不会减少,因此只能到达 y0y \ge 0 的区域。
    • 如果只使用 U,D,LU,D,L 三个按钮,则 xx 坐标永远不会增加,因此只能到达 x0x \le 0 的区域。
    • 如果只使用 R,D,LR,D,L 三个按钮,则 yy 坐标永远不会增加,因此只能到达 y0y \le 0 的区域。

    更一般地,只要存在一个方向(上、下、左、右)我们完全不使用,那么所有点都必须位于该方向所允许的半平面内

    反过来,如果点集中同时存在:

    • x>0x > 0 的点(需要 RR 按钮),
    • x<0x < 0 的点(需要 LL 按钮),
    • y>0y > 0 的点(需要 UU 按钮),
    • y<0y < 0 的点(需要 DD 按钮),

    那么四个按钮都必不可少,无法只用三个按钮,答案就是 "NO"


    算法步骤

    对于每个测试用例:

    1. 初始化四个布尔变量:

      • posXposX:是否存在 xi>0x_i > 0 的点
      • negXnegX:是否存在 xi<0x_i < 0 的点
      • posYposY:是否存在 yi>0y_i > 0 的点
      • negYnegY:是否存在 yi<0y_i < 0 的点
    2. 遍历所有点,根据坐标更新这四个标志。

    3. 如果 posXposXnegXnegXposYposYnegYnegY 四个标志 同时为真,则输出 "NO",否则输出 "YES"


    正确性证明

    充分性:若四个标志不全为真,则至少有一个方向(例如 x>0x>0 的方向)没有点。此时我们可以选择 不使用该方向对应的按钮,只使用其余三个按钮。由于所有点的坐标在该方向上的分量都不大于 00(或都不小于 00),我们可以通过逐层移动(类似“扫描线”方法)访问所有点。例如,若所有点满足 x0x \ge 0,则可以用 U,DU,D 在每一列上下移动,用 RR 向右推进。因此答案为 "YES"

    必要性:若四个标志全为真,则存在点需要 RR、存在点需要 LL、存在点需要 UU、存在点需要 DD。任何三个按钮都无法同时满足这四个方向的需求,因此答案为 "NO"


    复杂度分析

    • 每个测试用例只需遍历 nn 个点,时间复杂度 O(n)O(n)
    • 空间复杂度 O(1)O(1)(不考虑输入存储)。

    参考代码(C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            bool posX = false, negX = false, posY = false, negY = false;
            for (int i = 0; i < n; ++i) {
                int x, y;
                cin >> x >> y;
                if (x > 0) posX = true;
                if (x < 0) negX = true;
                if (y > 0) posY = true;
                if (y < 0) negY = true;
            }
            if (posX && negX && posY && negY) {
                cout << "NO\n";
            } else {
                cout << "YES\n";
            }
        }
        return 0;
    }
    
    • 1

    信息

    ID
    6214
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    递交数
    3
    已通过
    1
    上传者