洛谷P1034 矩形覆盖

1 篇文章 0 订阅
1 篇文章 0 订阅

洛谷P1034 矩形覆盖

这是一道简单的搜索题,但是非常难想到(据说当年的这题,全国没有一个人完全做对)。

首相我们来分析下,由于题目说矩形不能相互重合,即不能相交,并且k<=4。 那么我们可以分别写出矩形的排列方式。

1、当k=1时,就是一个大矩形,求所有点的左上右下的两个点。

2、当k=2时,有如下两个排列方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WZVvzsZk-1581827271841)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1581825053671.png)]

那么怎么计算呢?

对于左图,我们先将原先的点,按照y坐标升序排序,然后循环选择中间点,1i之间用一个矩形,i+1n再用一个矩形。

而右图,按x坐标升序排序,之后的操作一样

3、当k=3时,有如下六种方式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GEBTIJdo-1581827271843)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1581826760296.png)]

有了对k=2的分析基础,我相信,k=n的dfs深搜应该不难,就是一遍遍画矩形画下去,注意剪枝就行了,我自己写的时候,由于一开始没有在dfs中穿数组,导致每一遍for都要用一个sort,导致最后一个点超时了,后来改了改才过的。

其实仔细想想挺简单的。

上代码:

#include <bits/stdc++.h>
#define ull unsigned long long 
using namespace std;
const int maxn=1e2+7;
int n,k,ans=0x7fffffff;
struct Node{
    int x,y,id;
}node[maxn];
bool cmp(Node xx,Node yy){
    if(xx.x==yy.x)
        return xx.y<yy.y;
    return xx.x<yy.x;
}
bool cmp1(Node xx,Node yy){
    if(xx.y==yy.y)
        return xx.x<yy.x;
    return xx.y<yy.y;
}
void dfs(int ctk,int sum,int tp,Node n1[maxn],Node n2[maxn]){
    if(ctk>k || sum>ans)
        return;
    if(tp>n){
        if(ctk==k)
            ans=min(sum,ans);
        return;
    }
    int downx=0x7fffffff,downy=0x7fffffff,upx=-1,upy=-1;
    sort(n1+tp,n2+1+n,cmp);
    for(int i=tp;i<=n;i++){
        downx=min(node[i].x,downx);
        downy=min(node[i].y,downy);
        upx=max(node[i].x,upx);
        upy=max(node[i].y,upy);
        dfs(ctk+1,sum+(upx-downx)*(upy-downy),i+1,n1,n2);
    }
    downx=0x7fffffff,downy=0x7fffffff,upx=-1,upy=-1;
    sort(n2+tp,n2+n+1,cmp1);
    for(int i=tp;i<=n;i++){
        downx=min(node[i].x,downx);
        downy=min(node[i].y,downy);
        upx=max(node[i].x,upx);
        upy=max(node[i].y,upy);
        dfs(ctk+1,sum+(upx-downx)*(upy-downy),i+1,n1,n2);
    }
}
int main(){
    //freopen(".in","r",stdin);
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&node[i].x,&node[i].y);
        node[i].id=i;
    }
    dfs(0,0,1,node,node);
    printf("%d",ans);
return 0;
}

i].id=i;
}
dfs(0,0,1,node,node);
printf("%d",ans);
return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值