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

你可能感兴趣的:(USACO)