USACOTraining.Packing Rectangles

这道题确实是公认的USACO Tainning Section1中最BT的一道,题目大意是有4个矩形,问所需要的最小面积的盒子把这些矩形装起来。

学习别人Blog上的方法后过的。

就是枚举出所有的情况A(4, 4) * (2 ^ 4).

1 #include <iostream>
2 #include <string>
3 #include <algorithm>
4 #include <string.h>
5 #include <vector>
6 #include <math.h>
7 #include <time.h>
8  using namespace std;
9
10  const int INF = 40005;
11
12 struct REC
13 {
14 int w, h;
15 REC(){}
16 REC(int ww, int hh) : w(ww), h(hh)
17 {
18 if(w > h) swap(w, h);
19 }
20 bool operator < (const REC &t) const
21 {
22 if(w != t.w) return w < t.w;
23 else return h < t.h;
24 }
25 }rec[4];
26
27 int use[4];
28 int repeat[1005][1005];
29 int fmaxArea;
30 vector<REC>ans;
31
32 int fmax(int a, int b) {return max(a, b);}
33 int fmax(int a, int b, int c) {return max(max(a, b), c);}
34 int fmax(int a, int b, int c, int d) {return max(max(a, b), max(c, d));}
35
36 void kill(int w, int h)
37 {
38 if(w * h < fmaxArea)
39 {
40 fmaxArea = w * h;
41 ans.clear();
42 ans.push_back(REC(w, h));
43 }
44 else if(w * h == fmaxArea)
45 {
46 ans.push_back(REC(w, h));
47 }
48 }
49
50 void out()
51 {
52 memset(repeat, 0, sizeof(repeat));
53 sort(ans.begin(), ans.end());
54
55 printf("%d\n", fmaxArea);
56 for(int i = 0; i < ans.size(); i++)
57 {
58 int w = ans[i].w;
59 int h = ans[i].h;
60
61 if(repeat[w][h] == 0)
62 {
63 repeat[w][h] = 1;
64 printf("%d %d\n", w, h);
65 }
66 }
67 }
68
69 void sol()
70 {
71 int ww, hh;
72 int w1 = rec[use[0]].w;
73 int w2 = rec[use[1]].w;
74 int w3 = rec[use[2]].w;
75 int w4 = rec[use[3]].w;
76
77 int h1 = rec[use[0]].h;
78 int h2 = rec[use[1]].h;
79 int h3 = rec[use[2]].h;
80 int h4 = rec[use[3]].h;
81
82 //1
83 ww = w1+w2+w3+w4;
84 hh = fmax(h1,h2,h3,h4);
85 kill(ww, hh);
86
87 //2
88 ww = fmax(w1+w2+w3,w4);
89 hh = fmax(h1,h2,h3)+h4;
90 kill(ww, hh);
91
92 //3
93 ww = fmax(w1+w2,w3)+w4;
94 hh = fmax(h1+h3,h2+h3,h4);
95 kill(ww, hh);
96
97 //4
98 ww = w1+w2+fmax(w3,w4);
99 hh = fmax(h1,h3+h4,h2);
100 kill(ww, hh);
101
102 //5
103 if(h3 >= h2 + h4) ww = fmax(w1,w3+w2,w3+w4);
104 else if(h3 > h4) ww = fmax(w1+w2,w2+w3,w3+w4);
105 else if(h3 == h4) ww = fmax(w1+w2,w3+w4);
106 else if(h3 > h4 - h1) ww = fmax(w1+w2,w1+w4,w3+w4);
107 else ww = fmax(w2,w1+w4,w3+w4);
108
109 hh = fmax(h1+h3,h2+h4);
110 kill(ww, hh);
111 }
112
113 void rot(int x)
114 {
115 if(x == 4)
116 {
117 sol();
118 return;
119 }
120 rot(x + 1);
121 swap(rec[x].h, rec[x].w);
122 rot(x + 1);
123 swap(rec[x].h, rec[x].w);
124 }
125
126 void dfs(int x)
127 {
128 if(x == 4)
129 {
130 //说明4个都选好位置放下
131 //然后选择方向
132 rot(0);
133 return;
134 }
135
136 for(int i = 0; i < 4; i++)
137 {
138 if(use[i] == -1)
139 {
140 use[i] = x;
141 dfs(x + 1);
142 use[i] = -1;
143 }
144 }
145 }
146
147 void go()
148 {
149 //枚举所有的排列及翻转
150 fmaxArea = INF;
151 memset(use, -1, sizeof(use));
152 dfs(0);
153 out();
154 }
155
156 int main()
157 {
158 freopen("packrec.in", "r", stdin);
159 freopen("packrec.out", "w", stdout);
160
161 for(int i = 0; i < 4; i++)
162 scanf("%d%d", &rec[i].w, &rec[i].h);
163 go();
164 }

感谢以下链接:

http://sjtulibing.spaces.live.com/blog/cns!2F17193726A8CFC0!139.entry

原文地址:https://www.cnblogs.com/litstrong/p/1709656.html