USACO s1.4Packing Rectangles

    技术2024-11-25  42

    题目大意:给出4个矩形(1<=任意边长<=50),寻找最小的矩形可以竖直容纳给出的4个矩形.

    思路:

    有以上6种情况的堆放方式.再通过排列与旋转枚举所有情况.另外,第4第5种计算的结果相同,所以合并为一种情况.所以总共枚举有4! * 2^4 *5 = 1920.(其中有不少重复的情况,如第1种只需枚举1种排列即可).

    schema 1 :

    [ 0123 ]

    wid=wid0+wid1+wid2+wid3 , ht=max(ht0,ht1,ht2,ht3);

    schema 2:

    [ 012 ]

    [ 333 ]

    wid=max(wid0+wid1+wid2,wid3) , ht=max(ht0,ht1,ht2)+ht3;

    schema 3:

    [ 013 ]

    [ 223 ]

    wid=max(wid0+wid1,wid2)+wid3 , ht=max(wid3,max(wid0,wid1)+wid2);

    schema 4/5:

    [ 023 ]

    [ 123 ]

    wid=max(wid0,wid1)+wid2+wid3 , ht=max(ht0+ht1,ht2,ht3);

    schema 6:

    [ 23 ]

    [ 01 ]

    wid=max(

    wid0+wid1,

    wid0+wid3(当 ht0>ht1,否则03无法接触),

    wid1+wid2(当 ht1>ht0,否则12无法接触) ,

    wid2+wid3(当 ht1+ht3>ht0,否则23无法接触),

    wid2,

    wid3)

    ht=max(ht0+ht2,ht1+ht3).

    代码:

    //看着usaco的代码写的~~

    /* ID:sheshao1 LANG:C++ TASK:packrec */ #include <cstdio> #include <cstring> struct Rect { int wid; int ht; }; Rect r[4],rcd[4]; bool used[4]={0}; bool bestht[51*2]={0}; int bestarea=100000; int max(int a, int b) { return a > b ? a : b; } int min(int a, int b) { return a < b ? a : b; } void Record(Rect r) { if(r.wid*r.ht < bestarea) { bestarea=r.wid*r.ht; memset(bestht,0,sizeof(bestht)); bestht[min(r.wid,r.ht)]=1; } else if(r.wid*r.ht==bestarea) bestht[min(r.wid,r.ht)]=1; } void Check(Rect *r) { Rect big={0,0}; int i; /*schema 1: 0123 */ for(i=0;i<4;i++){ big.wid+=r[i].wid; big.ht=max(big.ht,r[i].ht); } Record(big); /*schema 2: 012 333 */ big.wid=max(r[3].wid,r[0].wid+r[1].wid+r[2].wid); big.ht=max(r[0].ht,max(r[1].ht,r[2].ht))+r[3].ht; Record(big); /*schema 3: 013 223 */ big.wid=max(r[2].wid,r[0].wid+r[1].wid)+r[3].wid; big.ht=max(r[3].ht,max(r[0].ht,r[1].ht)+r[2].ht); Record(big); /*schema 4/5: 023 123 */ big.wid=max(r[0].wid,r[1].wid)+r[2].wid+r[3].wid; big.ht=max(r[0].ht+r[1].ht,max(r[2].ht,r[3].ht)); Record(big); /*schema 6: 23 01 */ /* 0+1 */ big.wid=r[0].wid+r[1].wid; /* 1+2 */ if(r[1].ht>r[0].ht) big.wid=max(big.wid,r[1].wid+r[2].wid); /* 0+3 */ if(r[0].ht>r[1].ht) big.wid=max(big.wid,r[0].wid+r[3].wid); /* 2+3 */ if(r[0].ht+r[2].ht>r[1].ht) big.wid=max(big.wid,r[2].wid+r[3].wid); /* 2 */ big.wid=max(big.wid,r[2].wid); /* 3 */ big.wid=max(big.wid,r[3].wid); big.ht=max(r[0].ht+r[2].ht,r[1].ht+r[3].ht); Record(big); } void Rotate(Rect *rcd,int l) { if(l==4){ Check(rcd); return ; } int t; Rotate(rcd,l+1); t=rcd[l].wid , rcd[l].wid=rcd[l].ht , rcd[l].ht=t; Rotate(rcd,l+1); t=rcd[l].wid , rcd[l].wid=rcd[l].ht , rcd[l].ht=t; } void Permute(int l) { int i; if(l==4){ Rotate(rcd,0); return ; } for(i=0;i<4;i++){ if(!used[i]){ used[i]=1; rcd[l]=r[i]; Permute(l+1); used[i]=0; } } } /* void Permute(Rect *r, int n) { Rect t; int i; if(n == 4) checkrotate(r, 0); for(i=n; i<4; i++) { t = r[n], r[n] = r[i], r[i] = t; checkpermute(r, n+1); t = r[n], r[n] = r[i], r[i] = t; } }*/ int main() { FILE *fin,*fout; fin=fopen("packrec.in","r"); fout=fopen("packrec.out","w"); int i; for(i=0;i<4;i++) fscanf(fin,"%d %d",&r[i].wid,&r[i].ht); Permute(0); fprintf(fout,"%d/n",bestarea); for(i=1;i<101;i++) if(bestht[i]) fprintf(fout,"%d %d/n",i,bestarea/i); return 0; }  

    最新回复(0)