zoukankan      html  css  js  c++  java
  • Perfect Rectangle(完美矩形)

    我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域。

    每个矩形用左下角的点和右上角的点的坐标来表示。例如, 一个单位正方形可以表示为 [1,1,2,2]。 ( 左下角的点的坐标为 (1, 1) 以及右上角的点的坐标为 (2, 2) )。

    示例 1:

    rectangles = [
      [1,1,3,3],
      [3,1,4,2],
      [3,2,4,4],
      [1,3,2,4],
      [2,3,3,4]
    ]
    
    返回 true。5个矩形一起可以精确地覆盖一个矩形区域。
    
     

    示例 2:

    rectangles = [
      [1,1,2,3],
      [1,3,2,4],
      [3,1,4,2],
      [3,2,4,4]
    ]
    
    返回 false。两个矩形之间有间隔,无法覆盖成一个矩形。
    
     

    示例 3:

    rectangles = [
      [1,1,3,3],
      [3,1,4,2],
      [1,3,2,4],
      [3,2,4,4]
    ]
    
    返回 false。图形顶端留有间隔,无法覆盖成一个矩形。
    
     

    示例 4:

    rectangles = [
      [1,1,3,3],
      [3,1,4,2],
      [1,3,2,4],
      [2,2,4,4]
    ]
    
    返回 false。因为中间有相交区域,虽然形成了矩形,但不是精确覆盖。

    这道题我在写前两个解法的时候还没ac通过,但是已经忍不住要写了。思路还是很清晰的,遍历矩形,算有没有重合,面积累加,最后看看总面积是不是最大范围的覆盖的矩形的面积。
    第一遍暴力解法:
    class Solution {
    public:
        bool Cover(vector<int>& a, vector<int>&b)
        {
            if (min(a[0], a[2]) >= max(b[0], b[2]) || max(a[0], a[2]) <= min(b[0], b[2])
                || min(a[1], a[3]) >= max(b[1], b[3]) || max(a[1], a[3]) <= min(b[1], b[3]))
            {
                return false;
            }
            return true;
        }
        bool isRectangleCover(vector<vector<int>>& rectangles) {
            int minx, miny, maxx, maxy;
            minx = miny = INT_MAX;
            maxx = maxy = INT_MIN;
            long long int sum = 0;
            for (int i = 0; i < rectangles.size();i++)
            {
                for (int r = 0; r < i;r++)
                {
                    if (Cover(rectangles[i], rectangles[r]))
                    {
                        return false;
                    }
                }
                minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
                miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
                maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
                maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
                sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
            }
            return sum == (maxx - minx)*(maxy - miny);
        }
    };

    果不其然挂了,测试最后两组都是3w+的数据量

    第二遍:四叉树解法

    class QuadNode
    {
    public:
        enum{
            quad_1,//四个象限
            quad_2,
            quad_3,
            quad_4,
            quad_count,
        };
        vector<vector<int>>* data;
        QuadNode* Children[quad_count];//孩子指针,数组大小为8
        QuadNode* Parent;//父节点指针
        typedef std::list<int> RecList;
        typedef std::list<int>::iterator RecListIter;
        RecList rectlist;//携带的参数  实体列表
        int quad;//在父节点中的象限
        int deep;//自己所在的层索引
        int minx,miny;
        int maxx,maxy;
        QuadNode(vector<vector<int>>* data, int x1, int x2, int y1, int y2, int dp, int qd)
        {
            minx = x1;
            maxx = x2;
            miny = y1;
            maxy = y2;
            deep = dp;
            quad = qd;
            Parent = NULL;
            this->data = data;
            memset(Children, 0, sizeof(Children));
        }
        ~QuadNode()
        {
            for (int i = 0; i < quad_count; i++)
            {
                if (Children[i])
                {
                    delete Children[i];
                    Children[i] = NULL;
                }
            }
            rectlist.clear();
        }
        QuadNode* GetDeepest(int index)
        {
            if (deep > 0)
            {
                //4个孩子都要创建
                for (int r = 0; r < QuadNode::quad_count; r++)
                {
                    if (!Children[r])
                    {
                        int ix = r == QuadNode::quad_1 || r == QuadNode::quad_3 ? minx : (minx + maxx) / 2;
                        int ax = r == QuadNode::quad_1 || r == QuadNode::quad_3 ? (minx + maxx) / 2 : maxx;
    
                        int iy = r == QuadNode::quad_1 || r == QuadNode::quad_2 ? miny : (miny + maxy) / 2;
                        int ay = r == QuadNode::quad_1 || r == QuadNode::quad_2 ? (miny + maxy) / 2 : maxy;
                        QuadNode *node = new QuadNode(data, ix, ax, iy, ay, deep - 1, r);
                        node->Parent = this;
                        Children[r] = node;
                    }
                    if (Children[r]->CheckInRange(index))
                    {
                        return Children[r]->GetDeepest(index);
                    }
                }
            }
            return this;
        }
        bool CheckInRange(int index)
        {
            if ((*data)[index][0] >= minx && (*data)[index][2] <= maxx && (*data)[index][1] >= miny && (*data)[index][3] <= maxy)
            {
                return true;
            }
            return false;
        }
        bool CheckCover(int index)
        {
            QuadNode* n = GetDeepest(index);
            QuadNode* parent = n->Parent;
            while (parent)
            {
                if (parent->CheckWithTrianglelist(index))
                {
                    return true;
                }
                parent = parent->Parent;
            }
    
            if (n->CollisionCheck(index))
                return true;
            n->rectlist.push_back(index);
            return false;
        }
        bool CollisionCheck(int index)
        {
            return CheckWithTrianglelist(index) || CheckWithSubSpace(index);
        }
        bool CheckWithTrianglelist(int index)
        {
            RecListIter itr = rectlist.begin();
            while (itr != rectlist.end())
            {
                int id = *itr;
                if (Cover((*data)[id], (*data)[index]))
                {
                    return true;
                }
                itr++;
            }
            return false;
        }
    
        bool CheckWithSubSpace(int index)
        {
            bool collision = false;
            for (int i = 0; i < quad_count && Children[i]; i++)
            {
                int vec[] = { minx, miny, maxx, maxy };
                vector<int> para(vec, vec + 4);
                if (Cover((*data)[index], para))
                {
                    collision |= Children[i]->CollisionCheck(index);
                }
                if (collision)
                {
                    return true;
                }
            }
            return false;
        }
    
        bool Cover(vector<int>& a, vector<int>&b)
        {
            if (min(a[0], a[2]) >= max(b[0], b[2]) || max(a[0], a[2]) <= min(b[0], b[2])
                || min(a[1], a[3]) >= max(b[1], b[3]) || max(a[1], a[3]) <= min(b[1], b[3]))
            {
                return false;
            }
            return true;
        }
    };
    class Solution {
    public:
        int GetMax2Power(int xmax, int ymax, int& lg)
        {
            int max = xmax;
            if (ymax > max)
                max = ymax;
            if ((max & (max - 1)) == 0)
            {
                double L = log(max*1.0) / log(2.0);
                lg = (int)L + 1;
                return max;
            }
            else
            {
                double L = log(max*1.0) / log(2.0);
                lg = (int)L + 2;
                return (int)pow(2 * 1.0, lg - 1.0);
            }
        }
        bool isRectangleCover(vector<vector<int>>& rectangles) {
            int minx, miny, maxx, maxy;
            minx = miny = INT_MAX;
            maxx = maxy = INT_MIN;
            long long int sum = 0;
            for (int i = 0; i < rectangles.size(); i++)
            {
                minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
                miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
                maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
                maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
            }
            int mx = max(abs(maxx), abs(minx));
            int my = max(abs(maxy), abs(miny));
            int range, lg;
            range = GetMax2Power(mx, my, lg);
            //四叉树
            QuadNode* root = new QuadNode(&rectangles, -range, range, -range, range, lg, 0);
    
            for (int i = 0; i < rectangles.size();i++)
            {
                if (root->CheckCover(i))
                {
                    return false;
                }
                sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
            }
            delete root;
            return sum == (maxx - minx)*(maxy - miny);
        }
    };

    以为没什么问题了,跑一下又超时了,真是恶心的一p啊。拿测试数据跑一跑发现,几乎95%的数据都在边界上,四叉树无法往下细化。写个四叉树容易吗???

    只能硬着头皮继续想了,果然没有想到。参考了下别人的歪门邪道,感觉前面写的东西都白瞎了。有时候解决问题,还得靠技巧。

    解法三:所有的矩形顶点,有且只有四个边角是只出现一次,剩下的顶点要么两次,要么四次

       long long int getHash(int x, int y)
        {
            long long int t = 2 << 16;
            return x*t + y;
        }
        bool isRectangleCover(vector<vector<int>>& rectangles) {
            int minx, miny, maxx, maxy;
            minx = miny = INT_MAX;
            maxx = maxy = INT_MIN;
            long long int sum = 0;
            unordered_set<long long int> st;
            for (int i = 0; i < rectangles.size(); i++)
            {
                minx = min(minx, min(rectangles[i][0], rectangles[i][2]));
                miny = min(miny, min(rectangles[i][1], rectangles[i][3]));
                maxx = max(maxx, max(rectangles[i][0], rectangles[i][2]));
                maxy = max(maxy, max(rectangles[i][1], rectangles[i][3]));
                sum += abs((rectangles[i][0] - rectangles[i][2])*(rectangles[i][1] - rectangles[i][3]));
                long long int lu = getHash(rectangles[i][0], rectangles[i][3]);
                long long int ld = getHash(rectangles[i][0], rectangles[i][1]);
                long long int ru = getHash(rectangles[i][2], rectangles[i][3]);
                long long int rd = getHash(rectangles[i][2], rectangles[i][1]);
                if (st.count(lu) == 0) st.insert(lu);
                else st.erase(lu);
                if (st.count(ld) == 0) st.insert(ld);
                else st.erase(ld);
                if (st.count(ru) == 0) st.insert(ru);
                else st.erase(ru);
                if (st.count(rd) == 0) st.insert(rd);
                else st.erase(rd);
            }
            
            return sum == (maxx - minx)*(maxy - miny) && st.size() == 4 
                && st.count(getHash(minx, miny)) == 1
                && st.count(getHash(minx, maxy)) == 1
                && st.count(getHash(maxx, miny)) == 1
                && st.count(getHash(maxx, maxy)) == 1;
        }

    吐血!

  • 相关阅读:
    CSU 1333 Funny Car Racing
    FZU 2195 检查站点
    FZU 2193 So Hard
    ZOJ 1655 FZU 1125 Transport Goods
    zoj 2750 Idiomatic Phrases Game
    hdu 1874 畅通工程续
    hdu 2489 Minimal Ratio Tree
    hdu 3398 String
    洛谷 P2158 [SDOI2008]仪仗队 解题报告
    POJ 1958 Strange Towers of Hanoi 解题报告
  • 原文地址:https://www.cnblogs.com/shit/p/9726245.html
Copyright © 2011-2022 走看看