洛谷 P1034 矩形覆盖 (NOIp提高组2002)

来源:互联网 发布:偷钱猫存钱罐淘宝 编辑:程序博客网 时间:2024/06/06 03:58

BFS

注释非常详细
好几个坐标的运算要多画画图

要注意第64行有一个非常简单的剪枝
然而没有就少了20分

//P1034 矩形覆盖//2017.5.16//#define LOCAL#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(){#ifdef LOCAL    freopen("data.in", "r", stdin);    freopen("data.out", "w", stdout);#endif    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;}
原创粉丝点击