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; }