USACO Training:Packing Rectangles
这应该是usaco上遇到的第一个BT题,而且是极其BT。硬是让我纠结了一整天。尤其是最后一种情况,种类繁多,参考了大牛的结题报告才过的。各种WA。刚开始活生生写了300多行代码。AC的时候还有180行。肯定还有很大的优化空间。被此题搅的脑残了,懒得改进了。想不出IOI三个小时怎么写得出来。看来都是牛人。佩服!
我开始觉得这个题应该就是枚举,但是要细心。因为只有4个矩形,4!X 2^4;空间要求不大。直接硬搜。但是主要是最后一种情况比较复杂,需要分为5类考虑。

( 1 ) h[2] == h[3];
( 2 ) h[2] >= h[0] + h[3];
( 3 ) h[3] >= h[1] + h[2];
( 4 ) h[2] > h[3] && h[2] < h[0] + h[3];
( 5 ) 其他;
以上图片及解题思路来自:http://blog.csdn.net/danmarner/archive/2006/11/14/1383092.aspx
/*
ID: like_091
PROG: packrec
LANG: C++
*/
#include<iostream>
#include<fstream>
using namespace std;
const int INF = 1000000;
short c, d;
//四个矩形的边长
struct Node{
int h, d;
}node[5];
//保存可能存在最小面积的队列
struct Set{
int m, s, e;
}p[2000], q[2000];
//快排自定义函数
int cmp(const void *a, const void *b){
Set *c = (Set *)a;
Set *d = (Set *)b;
if (c->m == d->m)
return c->s - d->s;
return c->m - d->m;
}
//入队
void enqueue(Set *p, int k, int m, int s, int e){
p[k].m = m;
p[k].s = s;
p[k].e = e;
}
int main(){
ifstream cin("packrec.in");
ofstream cout("packrec.out");
int x, y, mins, bu[10], hu[10], temp[10], totb, toth;
short i, j, k, l, f;
for (i = 1; i <= 4; i++)
cin>>node[i].d>>node[i].h;
for (i = 1; i <= 8; i++){
if (i % 2){
bu[i] = max(node[(i + 1) / 2].h, node[(i + 1) / 2].d);
hu[i] = min(node[(i + 1) / 2].h, node[(i + 1) / 2].d);
temp[i] = (i + 1) / 2;
}else {
bu[i] = min(node[i / 2].h, node[i / 2].d);
hu[i] = max(node[i / 2].h, node[i / 2].d);
temp[i] = i / 2;
}
}
mins = INF;
c = d = 0;
for (i = 1; i <= 8; i++)
for (j = 1; j <= 8; j++){
if (temp[i] == temp[j])
continue;
for (k = 1; k <= 8; k++){
if (temp[k] == temp[i] || temp[k] == temp[j])
continue;
for (l = 1; l <= 8; l++){
if (temp[l] == temp[k] || temp[l] == temp[i] || temp[l] == temp[j])
continue;
//按第一种方法
totb = bu[i] + bu[j] + bu[k] + bu[l];
toth = max(hu[i], hu[j]);
toth = max(toth, hu[k]);
toth = max(toth, hu[l]);
if (mins > totb * toth){
mins = totb * toth;
x = max(totb, toth);
y = min(totb, toth);
}else if (mins == totb * toth){
enqueue(p, c, mins, min(totb, toth), max(totb, toth));
c++;
}
//按第二种方法
totb = bu[j] + bu[k] + bu[l];
toth = max(hu[j], hu[k]);
toth = max(toth, hu[l]);
totb = max(totb, hu[i]);
toth += bu[i];
if (mins > toth *totb){
mins = toth * totb;
x = max(toth, totb);
y = min(toth, totb);
}else if (mins == toth * totb){
enqueue(p, c, mins, min(totb, toth), max(totb, toth));
c++;
}
//按第三种方法
toth = max(hu[i], bu[j] + max(hu[k], hu[l]));
totb = bu[i] + max(hu[j], bu[k] + bu[l]);
if (mins > toth * totb){
mins = toth * totb;
x = max(toth, totb);
y = min(toth, totb);
}else if (mins == toth * totb){
enqueue(p, c, mins, min(totb, toth), max(totb, toth));
c++;
}
//按第四种方法
totb = bu[i] + bu[j] + max(bu[k], bu[l]);
toth = max(max(hu[i], hu[j]), hu[k] + hu[l]);
if (mins > totb * toth){
mins = totb * toth;
x = max(totb, toth);
y = min(totb, toth);
}else if (mins == toth * totb){
enqueue(p, c, mins, min(totb, toth), max(totb, toth));
c++;
}
//第五种和第四种是一样的
//按第六种方法
toth = max(hu[i] + hu[l], hu[j] + hu[k]);
if (hu[k] == hu[l])
totb = max(bu[j] + bu[i], bu[k] + bu[l]);
else if (hu[k] >= hu[i] + hu[l]){
totb = max(bu[j], bu[i] + bu[k]);
totb = max(totb, bu[k] + bu[l]);
}else if (hu[l] >= hu[j] + hu[k]){
totb = max(bu[i], bu[j] + bu[l]);
totb = max(totb, bu[k] + bu[l]);
}else if (hu[k] > hu[l] && hu[k] < hu[i] + hu[l]){
totb = max(bu[k] + bu[i], bu[k] + bu[l]);
totb = max(totb, bu[i] + bu[j]);
}else {
totb = max(bu[l] + bu[j], bu[l] + bu[k]);
totb = max(totb, bu[i] + bu[j]);
}
if (mins > totb * toth){
mins = totb * toth;
x = max(totb, toth);
y = min(totb, toth);
}else if (mins == toth * totb){
enqueue(p, c, mins, min(totb, toth), max(totb, toth));
c++;
}
}
}
}
enqueue(q, d, mins, y, x);
d++;
for (f = 0; f < c; f++)
if (mins == p[f].m){
enqueue(q, d, p[f].m, p[f].s, p[f].e);
d++;
}
qsort(q, d, sizeof(q[0]), cmp);//对面积排序
cout<<q[0].m<<endl;
for (i = 0; i < d; i++)
if (q[0].m == q[i].m && (!i || q[i].s != q[i - 1].s))
cout<<q[i].s<<" "<<q[i].e<<endl;
return 0;
}
浙公网安备 33010602011771号