牛客题解 | 整理房间

题目

题目链接

题目难度:三星
考察点:计算几何

方法:计算几何、枚举

  1. 分析:
    对于这道题来说我们有如下需要考虑的地方:
    (1). 一个点A(x1,y1)围绕一个点B(x2,y2)逆时针旋转90°一次,对应坐标A的变化?旋转多次呢?
    我们都知道如果B是原点的话,那么逆时针旋转90°一次之后坐标A(x1,y1)将变为C(y1, x1),那么如果B不是原点呢?我们将整个坐标系进行移动,将B移动到原点,那么A的坐标就会变为(x1-x2,y1-y2),那么此时进行逆时针旋转90°,A的坐标就会变为C(y1-y2,x1-x2)。注意,此时C的坐标是相对于B点来说的,如果相对于原点来说的话,就变成D(y1-y2+x2,x1-x2+y2),那么总结一下:就是点A(x1,y1)围绕一个点B(x2,y2)逆时针旋转90°一次之后的坐标变为D(y1-y2+x2,x1-x2+y2)。如果旋转多次的话,就把A点变为D,继续循环下去(最多旋转3次,因为旋转4次就相当于没有旋转)
    (2). 如何判断4个点是否能够构成正方形?
    我们只要获取4条边的边长,如果4条边相等且不为0,同时满足有一个角是直角,那么这4个点就能够构成正方形。首先我们将这4个点按照x坐标排序,如果x坐标相同按照纵坐标排序(都是从小到大排序)。那么排完序之后的坐标记作p0,p1,p2,p3,那么4条边的边长分别为p0p1, p0p2 p1p3, p2p3,判断一个角是否为直角,可以判断它们的点乘是否为0,如果为0证明是直角,否则不是直角.
    (3). 如何计算移动最少次数使得四个点构成正方形呢?
    我们可以进行枚举,一共有4个点,每个点可以旋转4次,一共是4^4种方法,我们将这些方法全部枚举出来,获得最小值就好了。

算法实现:
(1).首先进行枚举,4个变量i,j,k,l分别表示4个点的旋转次数,那么移动次数就等于i+j+k+l
(2).对于旋转之后的4个点,我们判断是否能够组成正方形即可,判断是否为正方形的方法已经在上面叙述了。
(3). 输出最小移动次数。

  1. 复杂度分析:
    时间复杂度:O(4^4*n)
    空间复杂度:O(1)

  2. 代码:

#include <bits stdc++.h>
using namespace std;
struct Point {
    int x, y;
};
bool cmp(Point A, Point B) {
    if(A.x == B.x) return A.y &lt; B.y;
    return A.x &lt; B.x;
}
int Dis2(Point A, Point B) {
    return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
}
//AB⊥BC
bool isRightAngle(Point A, Point B, Point C) {
    int x = (B.x-A.x)*(C.x-B.x);
    int y = (B.y-A.y)*(C.y-B.y);
    return x+y==0;
}
bool isSqure(Point p[4]) {
    sort(p, p+4, cmp);
    int dis[4];
    dis[0] = Dis2(p[0], p[1]);
    dis[1] = Dis2(p[0], p[2]);
    dis[2] = Dis2(p[1], p[3]);
    dis[3] = Dis2(p[2], p[3]);
    sort(dis, dis+4);
    if(dis[0]==dis[3] &amp;&amp; dis[0] &amp;&amp; isRightAngle(p[1], p[0], p[2])) return true;
    return false;
}
Point rotate(Point A, Point B, int t) {
    Point tmp;
    for(int i=0; i<t; i++) { tmp.x="B.x" - a.y + b.y; tmp.y="A.x" b.x a="tmp;" } return a; point a[4], b[4], p[4]; int main() n; cin>&gt;n;
    while(n--) {
        for(int i=0; i&lt;4; i++) cin&gt;&gt;a[i].x&gt;&gt;a[i].y&gt;&gt;b[i].x&gt;&gt;b[i].y;
        int ans = 20;
        for(int i=0; i&lt;4; i++) {
            for(int j=0; j&lt;4; j++) {
                for(int k=0; k&lt;4; k++) {
                    for(int l=0; l&lt;4; l++) {
                        p[0] = rotate(a[0], b[0], i);
                        p[1] = rotate(a[1], b[1], j);
                        p[2] = rotate(a[2], b[2], k);
                        p[3] = rotate(a[3], b[3], l);
                        if(isSqure(p)) ans = min(ans, i+j+k+l);
                    }
                }
            }
        }
        if(ans == 20) ans = -1;
        cout&lt;</t;></bits>
posted @ 2025-03-07 11:05  wangxiaoxiao  阅读(9)  评论(0)    收藏  举报