• Hihocoder 1275 扫地机器人 计算几何


    题意:

    有一个房间的形状是多边形,而且每条边都平行于坐标轴,按顺时针给出多边形的顶点坐标
    还有一个正方形的扫地机器人,机器人只可以上下左右移动,不可以旋转
    问机器人移动的区域能不能覆盖整个房间

    分析:

    官方题解

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using std::abs;
    using std::swap;
    
    const int maxn = 1010;
    
    struct Point
    {
    	int x, y;
    	Point(int x = 0, int y = 0): x(x), y(y) {}
    	void read() { scanf("%d%d", &x, &y); }
    	Point operator - (const Point& t) const {
    		return Point(x - t.x, y - t.y);
    	}
    };
    
    int n, m;
    Point p[maxn], dir[maxn]; //dir是边的单位方向向量
    int angle[maxn]; //用叉积判断内外角,angle为正是外角,为负是内角
    
    int sign(int x) { if(!x) return 0; return x > 0 ? 1 : -1; }
    
    Point Normalize(Point A) {
    	return Point(sign(A.x), sign(A.y));
    }
    
    int Cross(Point A, Point B) { return A.x * B.y - A.y * B.x; }
    
    int Length(Point A) { if(A.x) return abs(A.x); return abs(A.y); }
    
    int left, right, top, bottom; //机器人沿某条边扫过的矩形
    
    //判断扫描区域是否与房间的某条边相交
    bool intersect() {
    	for(int i = 1; i <= n; i++) {
    		if(p[i].x <= left && p[i+1].x <= left) continue;
    		if(p[i].x >= right && p[i+1].x >= right) continue;
    		if(p[i].y <= bottom && p[i+1].y <= bottom) continue;
    		if(p[i].y >= top && p[i+1].y >= top) continue;
    		return true;
    	}
    	return false;
    }
    
    int main()
    {
    	int q; scanf("%d", &q);
    	while(q--) {
    		scanf("%d%d", &n, &m);
    		for(int i = 1; i <= n; i++) p[i].read();
    		p[n + 1] = p[1];
    		for(int i = 1; i <= n; i++) dir[i] = Normalize(p[i+1]-p[i]);
    		dir[0] = dir[n];
    		for(int i = 1; i <= n; i++) angle[i] = Cross(dir[i - 1], dir[i]);
    		angle[n + 1] = angle[1];
    
    		bool ok = true;
    		for(int i = 1; i <= n; i++) {
    			if(angle[i] < 0 && angle[i+1] < 0 && Length(p[i+1]-p[i]) < m) {
    				ok = false; break;
    			}
    
    			if(dir[i].x) {
    				int delta = m * dir[i].x;
    				left = p[i].x; right = p[i+1].x;
    				if(angle[i] > 0) left -= delta;
    				if(angle[i+1] > 0) right += delta;
    				top = p[i].y; bottom = top - delta;
    			} else {
    				int delta = m * dir[i].y;
    				top = p[i].y; bottom = p[i+1].y;
    				if(angle[i] > 0) top -= delta;
    				if(angle[i+1] > 0) bottom += delta;
    				left = p[i].x; right = left + delta;
    			}
    			if(left > right) swap(left, right);
    			if(bottom > top) swap(bottom, top);
    			if(intersect()) { ok = false; break; }
    		}
    
    		printf("%s
    ", ok ? "Yes" : "No");
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    oracle 17068
    Nginx
    B/S端开发工具DevExtreme Angular控件
    UI组件库Kendo UI for Angular入门指南教程
    DevExpress WinForms v21.1
    WPF应用界面开发入门教程
    界面控件Telerik UI for WinForm初级教程
    十六、内联style.html
    十五、css样式class的多种用法
    十四、系统修饰键
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/6591005.html
Copyright © 2020-2023  润新知