USACO-Packing Rectangles

来源:互联网 发布:网络教育英语b统考 编辑:程序博客网 时间:2024/06/07 18:25

http://ace.delos.com/usacoprob2?a=GOVL6gcgbQL&S=packrec

嗯,一道无比恶心的题。。。。

无标题

观察好这几个图形,基本上就要靠这几个图形做题了。这题恶心的地方除了这几个图形,还有就是暴搜的方法,要全排列生成4个矩形的排列,然后才能按照上面几个图形来划分cases。注意了,第四个和第五个图形是一样的,只不过把中间的一列和左边的一列交换了位置。还有一个恶心的地方就是最后一个图形了,这里是这道题无比恶心的源泉啊(+﹏+)~狂晕。。。。

至于第六个图形,主要是讨论下面两个矩阵对整个大矩阵的宽的影响。

具体的用笔画一下吧,不再累赘了。。。。

#include <iostream>#include <string.h>#include <cstdio>#include <algorithm>using namespace std;struct node{    int w,h;    friend bool operator < (node a,node b)    {        return a.w<b.w;    }}r[5];int per[5]={0,1,2,3,4};int sum=0,square=99999999;node f[1000];void swap(node &a){    int x;    x=a.w; a.w=a.h; a.h=x;}int max2(int xx,int yy){    return (xx>yy)?xx:yy;}int max3(int xx,int yy,int zz){    return (max2(max2(xx,yy),zz));}int max4(int xx,int yy,int zz,int aa){    return (max2(max2(xx,yy),max2(zz,aa)));}void check(int ww,int hh){    if (ww*hh<square)    {        square=ww*hh;        sum=0;        f[++sum].w=min(ww,hh); f[sum].h=max(ww,hh);    }    else if (ww*hh==square)    {        f[++sum].w=min(ww,hh);        f[sum].h=max(ww,hh);    }}void case1(node a,node b,node c,node d)        //图形1{    int ww=a.w+b.w+c.w+d.w;    int hh=max4(a.h,b.h,c.h,d.h);    check(ww,hh);}void case2(node a,node b,node c,node d)          //图形2{    int ww=max2(a.w+b.w+c.w,d.w);    int hh=max3(a.h,b.h,c.h)+d.h;    check(ww,hh);}void case3(node a,node b,node c,node d)       //图形3{    int ww=max2(a.w+b.w,c.w)+d.w;    int hh=max2(max2(a.h,b.h)+c.h,d.h);    check(ww,hh);}void case4(node a,node b,node c,node d)            //图形4和图形5{    int ww=a.w+max2(b.w,c.w)+d.w;    int hh=max3(a.h,b.h+c.h,d.h);    check(ww,hh);}void case5(node a,node b,node c,node d)      //无比恶心的图形6,注意好大于小于等于,注意.w和.h了。。。{    int ww=0;    if (c.h>=b.h+d.h)        ww=max3(a.w,b.w+c.w,c.w+d.w);    else if (c.h>d.h && c.h<b.h+d.h)        ww=max3(a.w+b.w,c.w+b.w,c.w+d.w);    else if (c.h<d.h && a.h+c.h>d.h)        ww=max3(a.w+b.w,a.w+d.w,c.w+d.w);    else if (d.h>=a.h+c.h)        ww=max3(b.w,a.w+d.w,c.w+d.w);    else if (c.h==d.h)        ww=max2(a.w+b.w,c.w+d.w);    int hh=max2(a.h+c.h,b.h+d.h);    check(ww,hh);}void work(node a,node b,node c,node d){    case1(a,b,c,d);    case2(a,b,c,d);    case3(a,b,c,d);    case4(a,b,c,d);    case5(a,b,c,d);}int main(){    freopen("packrec.in","r",stdin);    freopen("packrec.out","w",stdout);    for (int i=1;i<=4;i++)        cin>>r[i].w>>r[i].h;    //这里要用do..while,用while的话,第一种原始排列就没有了    do       //每一个swap都是矩阵的旋转    {        for (int i=1;i<=2;i++)        {            swap(r[1]);            for (int j=1;j<=2;j++)            {                swap(r[2]);                for (int k=1;k<=2;k++)                {                    swap(r[3]);                    for (int l=1;l<=2;l++)                    {                        swap(r[4]);                        work(r[per[1]],r[per[2]],r[per[3]],r[per[4]]);                    }                }            }        }    }while (next_permutation(per+1,per+5));     //全排列生成法,要感谢STL了    cout<<square<<endl;    sort(f+1,f+sum+1);    for (int i=1;i<=sum;i++)    {        if (f[i].w==f[i-1].w && f[i].h==f[i-1].h) continue;        cout<<f[i].w<<" "<<f[i].h<<endl;    }    return 0;}

借用了zephyrQ的思想:

http://www.cnblogs.com/kissfinger/archive/2011/03/08/1977720.html