1 条题解
-
0
题意分析
我们需要判断在一个给定的**直角多边形(所有边平行于坐标轴)**中,是否存在一个点,使得该点可以看到整个多边形内部的所有区域。换句话说,这个点与多边形内任意一点的连线都不与多边形的任何边相交。
解题思路
- 直角多边形的性质:直角多边形的边交替为水平边和垂直边,且顶点均为直角(90°或270°)。
- 关键观察:对于直角多边形,存在这样的观察点当且仅当该多边形是单调的(即可以被一条直线分割为两部分,每部分在该直线上的投影是连续的)。
- 具体条件:对于直角多边形,存在一个观察点当且仅当该多边形是凸的。但直角多边形的凸性判断可以简化为检查所有内角是否都是270°或90°且不包含“凹陷”部分。
- 简化条件:实际上,对于直角多边形,存在观察点的充要条件是多边形是星形的。对于直角多边形,可以通过检查是否存在一个点,使得该点与所有边的可见性不被阻挡。
- 实际方法:对于直角多边形,可以检查所有内角是否满足某些条件。更简单的方法是检查多边形是否为弱可见多边形,即是否存在一个点可以“看到”所有边。
正确代码(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
- 上传者