Rectangle

题目大意

求一个面积最小的矩形使其能容纳给定的n个矩形,这n个矩形在该矩形内不能有交,且不能旋转或翻转。

搜索

我们知道——最终方案中,不会存在任何一个矩形可以向左或向上移动。
也就是它们都是贴着的。
于是我们可以定义关键横坐标,初始时只有1,每加入一个矩形,就将其右边界往右一格所在设为关键横坐标。我们规定矩形的左边界必须在关键横坐标上,于是可以知道符合这个规则最后矩形都是贴在一起的。
那么每次枚举要放哪一个矩形,再枚举放在哪个关键横坐标上,接着我们需要二分其放在哪个纵坐标上,需要满足在合法的情况下使这个纵坐标最小,至于判定直接枚举已经放了的矩形看会不会撞。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int w[10],h[10],a[30],b[10][3];
int i,j,k,l,t,n,m,ans,sum,num,top,tot;
bool czy,bz[10];
bool check(int nx,int ny,int W,int H){
    int i;
    fo(i,1,tot)
        if (!(b[i][1]>nx+W-1||b[i][1]+w[b[i][0]]-1<nx||b[i][2]>ny+H-1||b[i][2]+h[b[i][0]]-1<ny)) return 0;
    return 1;
}
void dfs(int x){
    int i,j,k,l,r,mid,xx=0,yy=0;
    fo(i,1,tot) xx=max(xx,b[i][1]+w[b[i][0]]-1),yy=max(yy,b[i][2]+h[b[i][0]]-1);
    if (xx*yy>=ans) return;
    if (!x){
        ans=xx*yy;
        return;
    }
    fo(i,1,n)
        if (!bz[i]){
            bz[i]=1;
            fo(j,1,top){
                l=1;r=yy+1;
                while (l<r){
                    mid=(l+r)/2;
                    if (check(a[j],mid,w[i],h[i])) r=mid;else l=mid+1;
                }
                b[++tot][0]=i;
                b[tot][1]=a[j];
                b[tot][2]=l;
                a[++top]=a[j]+w[i];
                dfs(x-1);
                tot--;
                top--;
            }
            bz[i]=0;
        }
}
int main(){
    freopen("rectangle.in","r",stdin);freopen("rectangle.out","w",stdout);
    scanf("%d",&n);
    czy=1;
    fo(i,1,n){
        scanf("%d%d",&w[i],&h[i]);
        sum+=w[i];
        num+=h[i];
        if (w[i]!=1) czy=0;
    }
    ans=sum*num;
    a[top=1]=1;
    dfs(n);
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值