整理房间--牛客网--面试题

题目描述

又到了周末,小易的房间乱得一团糟。

他希望将地上的杂物稍微整理下,使每团杂物看起来都紧凑一些,没有那么乱。

地上一共有n团杂物,每团杂物都包含4个物品。第i物品的坐标用(ai,bi)表示,小易每次都可以将它绕着(xi,yi)逆时针旋转90^ \circ90∘,这将消耗他的一次移动次数。如果一团杂物的4个点构成了一个面积不为0的正方形,我们说它是紧凑的。

因为小易很懒,所以他希望你帮助他计算一下每团杂物最少需要多少步移动能使它变得紧凑。

输入描述:

第一行一个数n(1 <= n <= 100),表示杂物的团数。
接下来4n行,每4行表示一团杂物,每行4个数ai, bi,xi, yi, (-104 <= xi, yi, ai, bi <= 104),表示第i个物品旋转的它本身的坐标和中心点坐标。

输出描述:

n行,每行1个数,表示最少移动次数。

示例1

输入

4
1 1 0 0
-1 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-2 1 0 0
-1 1 0 0
1 -1 0 0
1 1 0 0
-1 1 0 0
-1 1 0 0
-1 1 0 0
2 2 0 1
-1 0 0 -2
3 0 0 -2
-1 1 -2 0

输出

1 -1 3 3

说明

对于第一团杂物,我们可以旋转第二个或者第三个物品1次。

参考代码:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <bitset>
#include <unordered_map>
#include <stack>
#include <queue>
#include <deque>
#include <limits.h>
#include <cstdio>
using namespace std;
 
struct Item{
    int a, b, x, y, state;
    Item(){
        state = 0;
    }
 
    void crot(){
        state = (state + 1) % 4;
        int dx = a-x, dy = b-y;
        a = x - dy;
        b = y + dx;
    }
 
    void input(){
        cin>>a>>b>>x>>y;
        state = 0;
    }
 
    bool operator ==(const Item &item2){
        return a==item2.a && b==item2.b;
    }
 
    Item operator +(const Item &it2){
        Item res;
        res.a = a + it2.a;
        res.b = b + it2.b;
        return res;
    }
 
    Item operator -(const Item &it2){
        Item res;
        res.a = a - it2.a;
        res.b = b - it2.b;
        return res;
    }
 
    static bool ortho(const Item &it1, const Item &it2){
        if(it1.a==0 && it1.b== 0) return 0;
        if(it2.a==0 && it2.b == 0) return 0;
        return it1.a * it2.a + it1.b * it2.b == 0;
    }
};
 
struct Pack{
    vector<Item> itemList;
    vector<Item*> itp;
    int step;
 
    Pack(){
        itemList = vector<Item>(4);
        itp = vector<Item*>(4, nullptr);
        for(int i=0; i<4; ++i) itp[i] = &itemList[i];
        step = INT_MAX;
    }
 
    void input(){
        for(int i=0; i<4;++i)
            itemList[i].input();
        step = INT_MAX;
    }
 
    bool isSqaure(){
        for(int i=1; i<4; ++i){
            if(i!=1) swap(itp[i], itp[1]);
            if(*itp[0]==*itp[1] || *itp[2]==*itp[3]) return 0;
            if(!(*itp[0] + *itp[1] == *itp[2] + *itp[3])) continue;
            if(!Item::ortho(*itp[0]- *itp[1], *itp[2] - *itp[3])) continue;
            if(Item::ortho(*itp[0]- *itp[2], *itp[0] - *itp[3])) return 1;
        }
        return 0;
    }
 
    void trySqaure(int rot_idx){
        for(int i=0; i<4; ++i){
            if(rot_idx == 0 && isSqaure()){
                int tmp_step = 0;
                for(int j=0; j<4; ++j) tmp_step += itemList[j].state;
                if(step > tmp_step) step = tmp_step;
            }
            if(rot_idx > 0) trySqaure(rot_idx - 1);
            itemList[rot_idx].crot();
        }
    }
};
 
int main()
{
    int n;
    cin>>n;
    Pack eRoom;
    for(int i=0; i<n; ++i){
        eRoom.input();
        eRoom.trySqaure(3);
        cout<<(eRoom.step > 16 ? -1: eRoom.step)<<endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值