/* ID: lucien23 PROG: packrec LANG: C++ */ /* *深度优先遍历,找出最优解 *此题是我做USACO到目前为止花时间最多的 *很郁闷 **/ #include<iostream> #include<fstream> #include<vector> #include<algorithm> using namespace std; typedef struct Rectangle { int width; int height; }Rectangle; bool comparer1(Rectangle rect1,Rectangle rect2) { return rect1.height*rect1.width<rect2.height*rect2.width; } bool comparer2(Rectangle rect1,Rectangle rect2) { return rect1.width<rect2.width; } int main() { ifstream infile("packrec.in"); ofstream outfile("packrec.out"); if(!infile || !outfile) { cout<<"file operation failure!"<<endl; return -1; } Rectangle rects[4]; int width,height; for (int i=0;i<4;i++) { infile>>width>>height; rects[i].width=min(width,height); rects[i].height=max(width,height); } //测试6种基本布局(实际只有5中,4,5是相同的) //对每一种布局依次遍历每种矩阵的摆放方式 // 每个矩阵都可能旋转90度,共4!*2^4=384种 // 找出最小的大矩阵 vector<Rectangle> vectorRect; Rectangle rect; for (int i=0;i<4;i++) { int icount=1; while(icount<=2){ if(icount==2)//矩阵旋转90度 { int temp=rects[i].height; rects[i].height=rects[i].width; rects[i].width=temp; } for (int j=0;j<4;j++) { if(i==j) continue; int jcount=1; while(jcount<=2){ if(jcount==2) { int temp=rects[j].height; rects[j].height=rects[j].width; rects[j].width=temp; } for (int k=0;k<4;k++) { if(i==k || j==k) continue; int kcount=1; while(kcount<=2){ if(kcount==2) { int temp=rects[k].height; rects[k].height=rects[k].width; rects[k].width=temp; } for (int t=0;t<4;t++) { if(i==t || j==t || k==t) continue; int tcount=1; while(tcount<=2){ if(tcount==2) { int temp=rects[t].height; rects[t].height=rects[t].width; rects[t].width=temp; } //布局一 height=max(max(max(rects[i].height,rects[j].height),rects[k].height),rects[t].height); width=rects[i].width+rects[j].width+rects[k].width+rects[t].width; rect.height=max(height,width); rect.width=min(height,width); vectorRect.push_back(rect); //布局二 if(rects[t].height>rects[j].width+rects[k].width) { height=max(max(rects[i].height,rects[j].height),rects[k].height)+rects[t].width; width=max(rects[i].width+rects[j].width+rects[k].width,rects[t].height); rect.height=max(height,width); rect.width=min(height,width); vectorRect.push_back(rect); } //布局三 if(rects[t].height>rects[j].width) { height=max(max(rects[i].height,rects[j].height)+rects[t].width,rects[k].height); width=max(rects[i].width+rects[j].width,rects[t].height)+rects[k].width; rect.height=max(height,width); rect.width=min(height,width); vectorRect.push_back(rect); } //布局四 height=max(max(rects[i].height,rects[k].height),rects[j].height+rects[t].height); width=max(rects[j].width,rects[t].width)+rects[i].width+rects[k].width; rect.height=max(height,width); rect.width=min(height,width); vectorRect.push_back(rect); //布局五,最麻烦的,左右两边其实是对称的情况,所以只考虑一边就行 if(rects[k].height>=rects[t].height) { if(rects[i].height+rects[t].height>rects[k].height && rects[i].width<=rects[t].width) {//这个条件通过镜像反射代表了两个条件 width=max(rects[i].width+rects[j].height,rects[k].width+rects[t].width); } }else if(rects[j].width+rects[k].height<=rects[t].height){ width=max(max(rects[j].height,rects[k].width)+rects[t].width,rects[i].width); }else{ width=max(rects[i].width,rects[t].width)+max(rects[j].height,rects[k].width); } height=max(rects[i].height+rects[t].height,rects[j].width+rects[k].height); rect.height=max(height,width); rect.width=min(height,width); vectorRect.push_back(rect); tcount++; } } kcount++; } } jcount++; } } icount++; } } sort(vectorRect.begin(),vectorRect.end(),comparer1);//按面积从小到大排序 vector<Rectangle>::iterator it=vectorRect.begin(); for (it++;it!=vectorRect.end();it++) { if(it->height*it->width > (it-1)->height*(it-1)->width) break; } sort(vectorRect.begin(),it,comparer2);//将最小面积的方案按宽度从小到大排序 vector<Rectangle>::iterator it2=vectorRect.begin(); outfile<<it2->height*it2->width<<endl; outfile<<it2->width<<" "<<it2->height<<endl; for (it2++;it2!=it;it2++) { if(it2->width==(it2-1)->width) continue; outfile<<it2->width<<" "<<it2->height<<endl; } infile.close(); outfile.close(); return 0; }