前言:

这是一道令人望而却步的题,没有什么技术难度却又很需要勇气。解决它所需要花费的时间实际并不长,但就是怕麻烦的这种心理障碍让我迟迟无法下手,真需要好好反省一下。

题目大意:

给出4个矩形的长宽,求能包含4个矩形的最小矩形的面积,并输出其长宽。

思路:

题目通过图片形式给出了6种基本组合方式(4、5其实是一种),只需要把4个矩形插入相应位置即可。通过全排列遍历所有插入方案,再通过四重循环遍历所有翻转方案(横放或竖放)。简单计算下:需要遍历一共5*4!*2^4个方案后才能确定最终答案。

代码:

/*
ID: lujunda1
LANG: C++
PROG: packrec
*/
#include<iostream>
#include<stdio.h>
#include<map>
#include<algorithm>
using namespace std;
int rect[4][2];
//rectangle 用于存储4个矩形的长宽,rect[i][0]表示第i个矩形的长度,rect[i][1]表示其宽度。 
int order[4]={0,1,2,3};
//顺序数组,每个基本排列中,交换矩形的位置。共有24种组合。 
int tmp[4][2];
//存储通过顺序处理和翻转处理后的矩形信息。 
int t[4];
//t[i]为1时,表示第i个矩形需要翻转90°,为0时不需要翻转。 
int min_size=1000000;
//表示最小面积 。 
int total;
//表示最小面积包含的方案数量。 
map<int,bool> mark;
struct result
{
	int length;
	int width;
}res[100];
//存储最小面积包含的所有方案。 
int max(int a,int b)
{
	return a>b?a:b;
}
int max(int a,int b,int c)
{
	return max(max(a,b),c);
}
int max(int a,int b,int c,int d)
{
	return max(max(a,b,c),d);
}
int cmp(const void* m,const void* n)
{
	return (*(result*)m).width-(*(result*)n).width;
}
void change()
//根据order[]和t[]来生成tmp[]。 
{
	for(int i=0;i<4;i++)
		for(int j=0;j<=1;j++)
			tmp[i][j]=rect[order[i]][j];
	//顺序处理 
	for(int i=0;i<4;i++)
		if(t[i])
			swap(tmp[i][0],tmp[i][1]);
	//翻转处理 
}
void updata(int length,int width)
//根据当前大矩形长宽来更新res[]。 
{
	if(length<width)
	//应题目的格式要求 
		swap(length,width);
	if(length*width<min_size)
	//当前大矩形的面积比min_size小时,更新minsize和res[]还有total以及mark[]。 
	{
		total=1;
		res[0].length=length;
		res[0].width=width;
		min_size=length*width;
		mark.clear();
		mark[width]=true;
	}
	else if(length*width==min_size&&!mark[width])
	//当前大矩形的面积与min_size相等且有新方案时,更新res[]和total。 
	{
		res[total].length=length;
		res[total++].width=width;
		mark[width]=true;
	}
}
void plan_1()
//根据题目所给的图,考虑5种情况(第4、第5个图为同一种情况)。根据每种情况求出大矩形的长宽。 
{
	int width=tmp[0][1]+tmp[1][1]+tmp[2][1]+tmp[3][1];
	int length=max(tmp[0][0],tmp[1][0],tmp[2][0],tmp[3][0]);
	updata(length,width);
}
void plan_2()
{
	int width=max(tmp[0][1]+tmp[1][1]+tmp[2][1],tmp[3][1]);
	int length=max(tmp[0][0],tmp[1][0],tmp[2][0])+tmp[3][0];
	updata(length,width);
}
void plan_3()
{
	int width=max(tmp[0][1]+tmp[1][1],tmp[2][1])+tmp[3][1];
	int length=max(max(tmp[0][0],tmp[1][0])+tmp[2][0],tmp[3][0]);
	updata(length,width);
}
void plan_4()
{
	if(tmp[0][1]<=tmp[1][1])
	{
		int width=tmp[1][1]+tmp[2][1]+tmp[3][1];
		int length=max(tmp[0][0]+tmp[1][0],tmp[2][0],tmp[3][0]);
		updata(length,width);
	}
}
void plan_5()
{
	if(tmp[0][1]<=tmp[1][1]&&tmp[1][0]<=tmp[3][0]&&tmp[0][1]+tmp[2][1]<=tmp[1][1]+tmp[3][1])
	{
		int width=tmp[1][1]+tmp[3][1];
		int length=max(tmp[0][0]+tmp[1][0],tmp[2][0]+tmp[3][0]);
		updata(length,width);
	}
}
void get_min()
//针对change()及plan_*()的调用。 
{
	change();
	plan_1();
	plan_2();
	plan_3();
	plan_4();
	plan_5();
}
void func()
{
	for(int i=0;i<24;i++)
	//四个数的全排列共有4!=24种情况。 
	{
		for(t[0]=0;t[0]<=1;t[0]++)
			for(t[1]=0;t[1]<=1;t[1]++)
				for(t[2]=0;t[2]<=1;t[2]++)
					for(t[3]=0;t[3]<=1;t[3]++)
					//4个矩形翻转共有2^4=16种情况。 
						get_min();
		next_permutation(&order[0],&order[4]);
		//调用next_permutation()寻找order[]的下一个排列。 
	}
}
int main()
{
	freopen("packrec.in","r",stdin);
	freopen("packrec.out","w",stdout);
	for(int i=0;i<4;i++)
		scanf("%d%d",&rect[i][0],&rect[i][1]);
	func();
	qsort(res,total,sizeof(res[0]),cmp);
	printf("%d\n",min_size);
	for(int i=0;i<total;i++)
		printf("%d %d\n",res[i].width,res[i].length);
}