Rectangle

来源:互联网 发布:加拿大2.8预测软件 编辑:程序博客网 时间:2024/06/04 23:26

题目大意

求一个面积最小的矩形使其能容纳给定的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);}
0 0
原创粉丝点击