zoukankan      html  css  js  c++  java
  • NOIP2002矩形覆盖[几何DFS]

    题目描述

    在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示。例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。

    这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。

    输入输出格式

    输入格式:

    n k xl y1 x2 y2 ... ...

    xn yn (0<=xi,yi<=500)

    输出格式:

    输出至屏幕。格式为:

    一个整数,即满足条件的最小的矩形面积之和。

    输入输出样例

    输入样例#1:
    4 2
    1 1
    2 2
    3 6
    0 7
    
    输出样例#1:
    4

     -------------------------------------------------------------------------------

    看上去好吓人----然而与计算几何基本无关

    DFS每个点,枚举矩形来覆盖那个点,搜完点更新答案

    别忘要一个矩形覆盖一点dfs后把矩形改回原来的状态

    就是那些几何运算的函数写的有点多

    并且naocan的犯了一个沙茶问题,竟然这样写判断:lx<=x<=rx

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath> 
    using namespace std;
    const int N=55,INF=1e9;
    struct point{
        int x,y;
        point(int a=0,int b=0):x(a),y(b){}
    }p[N];
    struct squ{
        int lx,ly,rx,ry;
        squ():lx(0),rx(0),ly(0),ry(0){}
    }s[N]; 
    int n,k,ans=INF;
    inline bool isCover(int x,int y,int i){
        if(s[i].lx<=x&&x<=s[i].rx && s[i].ly<=y&&y<=s[i].ry) return true;
        return false;
    }
    bool checkSqu(int i,int j){
        squ a=s[i],b=s[j];
        //if(a.lx==INF || b.lx==INF) return false;
        if(isCover(a.lx,a.ly,j)) return false;
        if(isCover(a.lx,a.ry,j)) return false;
        if(isCover(a.rx,a.ly,j)) return false;
        if(isCover(a.rx,a.ry,j)) return false;
        swap(a,b);swap(i,j);
        if(isCover(a.lx,a.ly,j)) return false;
        if(isCover(a.lx,a.ry,j)) return false;
        if(isCover(a.rx,a.ly,j)) return false;
        if(isCover(a.rx,a.ry,j)) return false;
        return true;
    }
    bool check(){
        for(int i=1;i<=k;i++)
            for(int j=1;j<=k;j++){
                if(i==j) continue;
                if(s[i].lx==INF||s[j].lx==INF) continue;
                if(!checkSqu(i,j)) return false;
            }
        return true;
    }
    int getS(){
        int sum=0;
        for(int i=1;i<=k;i++){
            squ &now=s[i];
            if(now.lx==INF) continue;
            sum+=(now.rx-now.lx)*(now.ry-now.ly);
        }
        return sum;
    }
    void cover(point p,int i){
        squ &a=s[i];
        if(a.lx>p.x) a.lx=p.x;
        if(a.ly>p.y) a.ly=p.y;
        if(a.rx<p.x) a.rx=p.x;
        if(a.ry<p.y) a.ry=p.y;
        //printf("cover%d %d %d %d %d
    ",i,s[i].lx,s[i].ly,s[i].rx,s[i].ry);
    }
    void dfs(int now){    //cout<<now<<" now
    ";
        if(now==n+1){    //cout<<getS()<<" s
    ";
            ans=min(ans,getS());
            return;
        }
        if(getS()>=ans) return;
        for(int i=1;i<=k;i++){
            squ tmp=s[i];//printf("hi%d %d %d %d %d
    ",i,s[i].lx,s[i].ly,s[i].rx,s[i].ry);
            cover(p[now],i);
            if(check()) dfs(now+1);
            s[i]=tmp;    //printf("tmp%d %d %d %d %d
    ",i,s[i].lx,s[i].ly,s[i].rx,s[i].ry);
        }
        //cout<<now<<" end
    ";
    }
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&p[i].y,&p[i].x);//daozhe
        }
        for(int i=1;i<=k;i++){
            s[i].lx=s[i].ly=INF;
            s[i].rx=s[i].ry=-INF;
        }
        dfs(1);
        cout<<ans;
    }
  • 相关阅读:
    C++(四十)— C++中一个class类对象占用多少内字节
    C++(三十九) — 主函数中增加调试信息
    C++(三十八) — 继承方式、访问控制、构造和析构、虚继承
    ambari部署Hadoop集群(1)
    小波分析和多尺度几何分析
    正则化与矩阵范数
    设计模式之:创建型设计模式
    设计模式六大原则(详细)
    UML类关系(依赖,关联,聚合,组合,泛化,实现)
    SSD详解
  • 原文地址:https://www.cnblogs.com/candy99/p/5785840.html
Copyright © 2011-2022 走看看