1.4 Packing Rectangles
有必要继续做一下USACO了,上一次做是一年半以前了,卡在这个Packing Rectangles 上很久了
IOI的题,不是我这种人能YY出来的,虽然题目上有提示但还是想不出该怎样枚举,只能baidu一下报告了
算法:
很单纯的枚举,枚举四个矩形的全排列,还有每个矩形宽和高的组合,共4!*2^4=384组,然后根据题目提示中的每组那5种情况,一共1920种,至于那5种情况,这里就不用在copy了,baidu到的解题报告上都是一样的
实现:
根据解题报告上的算法,完全自己实现的。写起来没用什么特别的技巧,但是小函数很多,比较繁琐。主要就是怎样枚举四个矩形的全排列,我这里偷了懒,直接用algorithm里的next_permutation,列举四个矩形宽和高的情况,使用了四重循环,我记得hhanger说过可以用位运算枚举,但是不知道怎么搞,暂时也没搜到。第一次写这么麻烦的题,接近200行……没想到居然一次就过了……
代码:
1 /*
2 ID:stevech1
3 LANG:C++
4 TASK:packrec
5 */
6
7 #include <cstdio>
8 #include <iostream>
9 #include <vector>
10 #include <fstream>
11 #include <algorithm>
12 #include <set>
13
14 using namespace std;
15
16 struct rect{
17 int w;
18 int h;
19 };
20
21 struct Comp{
22 bool operator() ( const rect &a, const rect &b )
23 {
24 return a.w < b.w;
25 }
26 };
27
28 int res=1000000;
29 set<rect,Comp> ans ;
30 rect r[4];
31 int per[4]={0,1,2,3};
32
33
34 int max2(const int &a,const int &b)
35 {
36 return a>b?a:b;
37 }
38
39 int max3(const int &a,const int &b,const int &c)
40 {
41 return max2(max(a,b),c);
42 }
43
44 int max4(const int &a,const int &b,const int &c,const int &d)
45 {
46 return max2(max(a,b),max(c,d));
47 }
48
49 int swap(rect &rr)
50 {
51 int t=rr.w;
52 rr.w=rr.h;
53 rr.h=t;
54 return 0;
55 }
56
57 int update(const int &wid,const int &hig)
58 {
59 int area=wid*hig;
60 rect t={0,0};
61 if(wid<hig)
62 {
63 t.w=wid;
64 t.h=hig;
65 }
66 else
67 {
68 t.w=hig;
69 t.h=wid;
70 }
71 if(area<res)
72 {
73 res=area;
74 ans.clear();
75 ans.insert(t);
76 return 0;
77 }
78 if(area==res)
79 {
80 ans.insert(t);
81 return 0;
82 }
83
84 return 0;
85 }
86
87 int case1(rect a,rect b,rect c,rect d)
88 {
89 int wi=a.w+b.w+c.w+d.w;
90 int hi=max4(a.h,b.h,c.h,d.h);
91 update(wi,hi);
92 return 0;
93 }
94
95
96 int case2(rect a,rect b,rect c,rect d)
97 {
98 int wi=max2(a.w+b.w+c.w,d.w);
99 int hi=max3(a.h,b.h,c.h)+d.h;
100 update(wi,hi);
101 return 0;
102 }
103
104 int case3(rect a,rect b,rect c,rect d)
105 {
106 int wi=max2(a.w+b.w,c.w)+d.w;
107 int hi=max3(a.h+c.h,b.h+c.h,d.h);
108 update(wi,hi);
109 return 0;
110 }
111
112 int case4(rect a,rect b,rect c,rect d)
113 {
114 int wi=a.w+b.w+max2(c.w,d.w);
115 int hi=max3(a.h,c.h+d.h,b.h);
116 update(wi,hi);
117 return 0;
118 }
119
120 int case5(rect a,rect b,rect c,rect d)
121 {
122 int wi=0;
123 int hi=max2(a.h+c.h,b.h+d.h);
124 if(c.h>=b.h+d.h)
125 wi=max3(a.w,b.w+c.w,c.w+d.w);
126 else if(c.h>d.h&&c.h<b.h+d.h)
127 wi=max3(a.w+b.w,c.w+b.w,c.w+d.w);
128 else if(d.h>c.h&&d.h<a.h+c.h)
129 wi=max3(a.w+b.w,a.w+d.w,d.w+c.w);
130 else if(d.h>=a.h+c.h)
131 wi=max3(b.w,a.w+d.w,c.w+d.w);
132 else if(c.h=d.h)
133 wi=max2(a.w+b.w,c.w+d.w);
134 update(wi,hi);
135 return 0;
136 }
137
138 int work(rect a,rect b,rect c,rect d)
139 {
140 case1(a,b,c,d);
141 case2(a,b,c,d);
142 case3(a,b,c,d);
143 case4(a,b,c,d);
144 case5(a,b,c,d);
145 }
146
147
148 int main()
149 {
150 int pp=0;
151 freopen("packrec.in","r",stdin);
152 freopen("packrec.out","w",stdout);
153 for(int i=0;i<4;i++)
154 {
155 cin>>r[i].w>>r[i].h;
156 }
157 do{
158 for(int i=0;i<2;i++)
159 {
160 swap(r[0]);
161 for(int j=0;j<2;j++)
162 {
163 swap(r[1]);
164 for(int p=0;p<2;p++)
165 {
166 swap(r[2]);
167 for(int q=0;q<2;q++)
168 {
169 swap(r[3]);
170 work(r[per[0]],r[per[1]],r[per[2]],r[per[3]]);
171 }
172 }
173 }
174 }
175
176 }while(next_permutation(per,per+4));
177
178 cout<<res<<endl;
179 for(set<rect,Comp>::iterator i=ans.begin();i!=ans.end();i++)
180 cout<<(*i).w<<" "<<(*i).h<<endl;
181 return 0;
182 }
这张截图还是很励志的: