zoukankan      html  css  js  c++  java
  • 题解 P1034 【矩形覆盖】

    注释非常详细
    好几个坐标的运算要多画画图
    要注意第64行有一个非常简单的剪枝
    然而没有就少了20分
    如下贴代码:

    代码:

    #include<cstdio>
    #include<iostream>//其实你也可以考虑用万能但本人不太习惯用,吱吱
    using namespace std;
    int n, m, ans = 250000 + 2, num;
    struct Node{
        int x, y;
    };
    struct Node node[51];
    struct Squre{
        int ax, ay;   //↙左下角(ax, ay) 
        //↘右下角(bx, ay) 
        int bx, by;   //↗右上角(bx, by)
        //↖左上角(ax, by) 
    };
    struct Squre s[7];
    bool is_involve(int i, int j){   //判断点i是否在矩形j内
        if (node[i].x < s[j].ax || node[i].x > s[j].bx) return false;
        if (node[i].y < s[j].ay || node[i].y > s[j].by) return false;
        return true;
    }
    bool judge(int j){   //判断新矩形j是否影响其他矩形
        for (int i = 1; i <= num; i++){
            if (i == j) continue;
            //方法:只要有某个矩形中有一个点在矩形j内 则有重叠 
            if (s[i].ax >= s[j].ax && s[i].ay >=s[j].ay && s[i].ax <= s[j].bx && s[i].ay <= s[j].by) return false;
            if (s[i].bx >= s[j].ax && s[i].ay >=s[j].ay && s[i].bx <= s[j].bx && s[i].ay <= s[j].by) return false;
            if (s[i].ax >= s[j].ax && s[i].by >=s[j].ay && s[i].ax <= s[j].bx && s[i].by <= s[j].by) return false;
            if (s[i].bx >= s[j].ax && s[i].by >=s[j].ay && s[i].bx <= s[j].bx && s[i].by <= s[j].by) return false;
        }
        return true;
    } 
    int _s(int i){   //计算第i个矩形的面积 
        return (s[i].by - s[i].ay) * (s[i].bx - s[i].ax);
    }
    int sum(){   //计算第i个矩形的面积 
        int _sum = 0;
        for (int i = 1; i <= num; i++)
            _sum = _sum + _s(i);
        return _sum;
    }
    void dfs(int i){   //对于每一个点(node[i].x, node[i].y) 
        //*
        if (i > n){
            ans = min(ans, sum());
    //      cout << endl;
    //      for (int i = 1; i <= num; i++){
    //          cout << s[i].ax << ", " << s[i].ay << "  -  " << s[i].bx << ", " << s[i].by << endl;
    //          cout << " + " << _s(i) << endl;
    //      }
    //      cout << sum() << endl;
            return ;
        }
        if (sum() >= ans) return ;   //Cut
        //1°加入前面的组 
        for (int j = 1; j <= num; j++){
            //1°- 1′可直接加入
            if (is_involve(i, j)){   //如果点i在矩形j内 
                dfs(i + 1);
            }
            else{   //1°- 2′不可直接加入 要扩大原有矩形
                int preax = s[j].ax, preay = s[j].ay, prebx = s[j].bx, preby = s[j].by;
                s[j].ax = min(node[i].x, s[j].ax);
                s[j].ay = min(node[i].y, s[j].ay);
                s[j].bx = max(node[i].x, s[j].bx);
                s[j].by = max(node[i].y, s[j].by);
                if (!judge(j)){   //1°- 2′- 1″扩大原有矩形后 与其他矩形重合 
                    s[j].ax = preax; s[j].ay = preay;
                    s[j].bx = prebx; s[j].by = preby;   //还原 
                    continue;
                }
                //1°- 2′- 2″扩大原有矩形后 不影响其他矩形
                dfs(i + 1); 
                s[j].ax = preax; s[j].ay = preay;
                s[j].bx = prebx; s[j].by = preby;   //还原 
            }
        }
        //2°自成一组 
        if (num < m){
            num++;
            s[num].ax = node[i].x; s[num].bx = node[i].x;
            s[num].ay = node[i].y; s[num].by = node[i].y;
            dfs(i + 1);
            num--;   //还原
        }
        return ;
    }
    
    int main(){
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            scanf("%d%d", &node[i].x, &node[i].y);
        dfs(1);
        cout << ans;//最后是将答案输出,这个不多说
        return 0;//程序到达了终点,程序:“可以睡觉啦”
    }
  • 相关阅读:
    java监听者模式
    使用tc编写流量控制脚本
    Android apk集成
    就这样
    嘴不笨来试试??太好玩儿了,看看谁厉害?
    老板的三句话
    电脑设置wifi
    JDBC
    使用git的一般操作
    模板引擎Velocity学习系列
  • 原文地址:https://www.cnblogs.com/Sworddust/p/11427795.html
Copyright © 2011-2022 走看看