这道题使用搜索,就如题目中所说的那样,四个矩形无论如何摆都可以归纳为6种方案中的一种,先用深度优先搜索枚举出4个矩形(以及横、竖摆放)的排列,然后考虑用这6种摆法哪种摆法面积最小,注意观察会发现,情况4、5求出的面积是一样的,所以略去情况4,共有5种情况

/**//*
ID: sdjllyh1
PROG: packrec
LANG: JAVA
complete date: 2008/11/18
author: LiuYongHui From GuiZhou University Of China
more article: www.cnblogs.com/sdjls
*/
import java.io.*;
import java.util.*;
public class packrec

{
private static rectangle[] originalRec = new rectangle[4];//从输入文件中读入的矩形数据
private static rectangle[] currentRec = new rectangle[4];//深度优先搜索得到的排列(每个排列又由于横、竖不同放法,有16种情况)
private static int smallestArea = 40001;//记录发现的最小面积
private static ArrayList solutions = new ArrayList();//记录发现的解
private static boolean[] used = new boolean[4];//用于深度优先搜索,记录哪些矩形已经属于排列中
public static void main(String[] args) throws IOException
{
init();
run();
output();
System.exit(0);
}
private static void run()
{
dfs(0);
}
private static void dfs(int dep)
{
//深度等于4,表示得到了一个排列
if (dep == 4)
{
considerFigure1();
considerFigure2();
considerFigure3();
considerFigure4();
considerFigure5();
}
else
{
for (int i = 0; i < 4; i++)
{
if (!used[i])
{
used[i] = true;
currentRec[dep] = originalRec[i];
dfs(dep + 1);
currentRec[dep] = originalRec[i].rotate();
dfs(dep + 1);
used[i] = false;
}
}
}
}
//考虑情况一,矩形位置关系:0123
private static void considerFigure1()
{
int x = 0;
int y = 0;
//compute x
for (int i = 0; i < 4; i++)
{
x += currentRec[i].x;
}
//compute y
for (int i = 0; i < 4; i++)
{
y = Math.max(y, currentRec[i].y);
}
dealSolution(new rectangle(x, y));
}
//考虑情况二,矩形位置关系:012
// 333
private static void considerFigure2()
{
int x = 0;
int y = 0;
//compute x
for (int i = 0; i < 3; i++)
{
x += currentRec[i].x;
}
x = Math.max(x, currentRec[3].x);
//compute y
for (int i = 0; i < 3; i++)
{
y = Math.max(y, currentRec[i].y);
}
y += currentRec[3].y;
dealSolution(new rectangle(x, y));
}
//考虑情况三,矩形位置关系:013
// 223
private static void considerFigure3()
{
int x = 0;
int y = 0;
//compute x
x = Math.max(currentRec[0].x + currentRec[1].x, currentRec[2].x);
x += currentRec[3].x;
//compute y
y = Math.max(currentRec[0].y + currentRec[2].y, currentRec[1].y + currentRec[2].y);
y = Math.max(y, currentRec[3].y);
dealSolution(new rectangle(x, y));
}
//考虑情况四,矩形位置关系:023
// 123
private static void considerFigure4()
{
int x = 0;
int y = 0;
//compute x
x = Math.max(currentRec[0].x, currentRec[1].x);
x += currentRec[2].x + currentRec[3].x;
//compute y
y = currentRec[0].y + currentRec[1].y;
y = Math.max(y, currentRec[2].y);
y = Math.max(y, currentRec[3].y);
dealSolution(new rectangle(x, y));
}
//考虑情况五,矩形位置关系:02
// 13
//方法如下,先把0、2上对其连在一起,把1、3下对其连在一起,然后再把上、下两部分逐渐靠近,直到接触
//至于为什么采用上面的过程,这是因为其它类似的过程会在枚举其它排列时出现
private static void considerFigure5()
{
int x = 0;
int y = 0;
//compute x
x = Math.max(currentRec[0].x + currentRec[2].x, currentRec[1].x + currentRec[3].x);
//compute y
//如果0.x<1.x 则0、3不可能接触,1、2可能会接触 此时y=max(0.y+1.y, 2.y+3.y, 1.y+2.y)
if (currentRec[0].x < currentRec[1].x)
{
y = Math.max(currentRec[0].y + currentRec[1].y, currentRec[2].y + currentRec[3].y);
y = Math.max(y, currentRec[2].y + currentRec[1].y);
}//如果0.x>1.x,则1、2不可能接触,0、3可能会接触,对应
else if (currentRec[0].x > currentRec[1].x)
{
y = Math.max(currentRec[0].y + currentRec[1].y, currentRec[2].y + currentRec[3].y);
y = Math.max(y, currentRec[0].y + currentRec[3].y);
}
else//否则可以用一条竖线把0、1和2、3分开
{
y = Math.max(currentRec[0].y + currentRec[1].y, currentRec[2].y + currentRec[3].y);
}
dealSolution(new rectangle(x, y));
}
private static void dealSolution(rectangle sol)
{
//if find a smaller solution
if (sol.area() < smallestArea)
{
smallestArea = sol.area();
solutions.clear();
solutions.add(sol);
}//if find a solution
else if (sol.area() == smallestArea)
{
solutions.add(sol);
}
}
private static void init() throws IOException
{
BufferedReader f = new BufferedReader(new FileReader("packrec.in"));
for (int i = 0; i < 4; i++)
{
StringTokenizer st = new StringTokenizer(f.readLine());
int side1 = Integer.parseInt(st.nextToken());
int side2 = Integer.parseInt(st.nextToken());
originalRec[i] = new rectangle(side1, side2);
}
f.close();
}
private static void output() throws IOException
{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("packrec.out")));
out.println(smallestArea);
Collections.sort(solutions);
Iterator it = solutions.iterator();
int lastShortSide = 0;
while (it.hasNext())
{
rectangle rect = (rectangle)it.next();
if (rect.shortSide != lastShortSide)
{
lastShortSide = rect.shortSide;
out.println(rect.toString());
}
}
out.close();
}
}
class rectangle implements Comparable

{
public int x;
public int y;
public int shortSide;
public int longSide;
public rectangle(int x, int y)
{
this.x = x;
this.y = y;
this.shortSide = Math.min(x, y);
this.longSide = Math.max(x, y);
}
public int compareTo(Object arg0)
{
rectangle rec1 = (rectangle)arg0;
if (this.shortSide < rec1.shortSide)
return -1;
else if (this.shortSide == rec1.shortSide)
return 0;
else
return 1;
}
public int area()
{
return this.shortSide * this.longSide;
}
public String toString()
{
return this.shortSide + " " + this.longSide;
}
public rectangle rotate()
{
return new rectangle(this.y, this.x);
}
}
浙公网安备 33010602011771号