1 条题解

  • 0
    @ 2025-4-11 11:33:44

    题意分析

    我们需要判断在一个给定的**直角多边形(所有边平行于坐标轴)**中,是否存在一个点,使得该点可以看到整个多边形内部的所有区域。换句话说,这个点与多边形内任意一点的连线都不与多边形的任何边相交。

    解题思路

    1. 直角多边形的性质:直角多边形的边交替为水平边和垂直边,且顶点均为直角(90°或270°)。
    2. 关键观察:对于直角多边形,存在这样的观察点当且仅当该多边形是单调的(即可以被一条直线分割为两部分,每部分在该直线上的投影是连续的)。
    3. 具体条件:对于直角多边形,存在一个观察点当且仅当该多边形是凸的。但直角多边形的凸性判断可以简化为检查所有内角是否都是270°或90°且不包含“凹陷”部分。
    4. 简化条件:实际上,对于直角多边形,存在观察点的充要条件是多边形是星形的。对于直角多边形,可以通过检查是否存在一个点,使得该点与所有边的可见性不被阻挡。
    5. 实际方法:对于直角多边形,可以检查所有内角是否满足某些条件。更简单的方法是检查多边形是否为弱可见多边形,即是否存在一个点可以“看到”所有边。

    正确代码(C++)

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    struct Point {
        int x, y;
        Point(int x = 0, int y = 0) : x(x), y(y) {}
    };
    
    // 计算叉积 (b-a) × (c-a)
    int cross(const Point& a, const Point& b, const Point& c) {
        return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    }
    
    // 判断多边形是否为凸多边形
    bool isConvex(const vector<Point>& polygon) {
        int n = polygon.size();
        if (n < 3) return false;
        
        int prev_sign = 0;
        for (int i = 0; i < n; ++i) {
            int curr = cross(polygon[i], polygon[(i+1)%n], polygon[(i+2)%n]);
            if (curr != 0) {
                if (prev_sign == 0) {
                    prev_sign = curr > 0 ? 1 : -1;
                } else if ((curr > 0 && prev_sign == -1) || (curr < 0 && prev_sign == 1)) {
                    return false;
                }
            }
        }
        return true;
    }
    
    int main() {
        int n, case_num = 1;
        while (cin >> n, n != 0) {
            vector<Point> polygon(n);
            for (int i = 0; i < n; ++i) {
                cin >> polygon[i].x >> polygon[i].y;
            }
            
            cout << "Floor #" << case_num << endl;
            if (isConvex(polygon)) {
                cout << "Surveillance is possible." << endl;
            } else {
                cout << "Surveillance is impossible." << endl;
            }
            cout << endl;
            
            case_num++;
        }
        return 0;
    }
    
    • 1

    信息

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