Once upon a time, there lived Catherine Ironfist, the Queen of Enroth. One day, she received the news of her father's death. So she sailed for Erathia to attend her father's funeral. Fearing the worst, she assembled a military fleet as her escort. On reaching the coast of Erathia, Catherine found an allied wizard's tower, devastated from battle and abandoned. There she learned that a black-hearted knight poisoned her father using a goblet of wine, and Erathia was falling to the enemies. And then, she mustered local armies, and marched to Erathia's castle, restoring lost land along the way.
During the battles, she found that the equipments for the soldiers were in urgent need. And she knew clearly that the best equipments were made by the battle dwarf's workshop in the world. The workshop's equipments were well known for the firmness and top-quality. "Cloak of the Undead King", "Armor of the Damned", "Angelic Helm" are the nonesuch ones. But unfortunately, the workshop was seated at the Erathia's castle, the territory under the enemy's control. So she sent a brave volunteer to come into the castle and asked for the workshop's help.
"It's our pleasure to help the righteous heroine." Rion, the leader of the workshop sent the message to Catherine, " We haven't enough resources to build the nonesuch equipments. So we'll try to offer the ordinary equipments as more as possible. Still, those ones are much better the equipments made by other workshops. But we have faced a difficult problem. The castle is in a state of siege. The guards prohibited the equipments to be carried away from the castle. We have to ask for the trade caravans' help. As you know, each trade caravan's capability of carrying equipments is limited. If they had carried a little more, they would be detected by the guards, which would lead them into the prison. So you have to arrange how to carry these equipments."
The workshop would offer helms, armors and boots. These three ones had different defend capabilities. Also, their weight and size were different from each other. What's more, Rion had told Catherine that if armed with those three ones together, they would form a set of equipments, which might provide much more defend capability. As far as the trade caravan was concerned, each one had its special weight limitation and size limitation. Catherine had to make the decision on how to arrange the transportation plan to provide her soldiers as more defend capabilities as possible. Could you help her to finish the plan?
Input
The input describes several test cases. The first line of input for each test case contains a single integer n, the number of trade caravans (0 <= n <= 100).
The following four lines describe the information of those equipments. The first line contains three integers w1, s1 and d1, indicating the weight, size and defend capabilities of the helm. The integers w2, s2 and d2 in the second line represent the weight, size and defend capabilities of the armor. Also, in the third line, w3, s3 and d3 are the weight, size and defend capabilities of the boot. The fourth line contains four integers c1, c2, c3 and d4. Among those integers, c1, c2, c3 are the number of helms, armors and boots in a set of equipments, d4 is the capability of this set.
In the test case, following those data are n lines, describing the carrying capabilities of the trade caravans. Each line contains two integers, xi and yi, indicating the weight limit and size limit of a trade caravan.
The input is terminated by a description starting with n = 0. This description should not be processed.
Note: Because of the trade caravans' carrying capabilities, you may assume the quantities of the helms, armors and boots will not exceed 500 respectively.
Output
Your program must compute the defend capability of the best carrying plan. That is, after having performed the carrying plan, the defend capability of the equipments which have been carried away from the castle should be the largest. For each test case in the input file, print the case number and a colon, and then the defend capability of those equipments.
Print a blank line between test cases.
Sample Input
3
1 1 3
5 6 10
2 1 2
1 1 1 50
1 1
5 6
2 1
0
Output for the Sample Input
Case 1: 50
2
3 #define MAXCARAVAN 100
4 #define MAXEQUIPMENT 500
5 #define HELM 0
6 #define ARMOR 1
7 #define BOOT 2
8
9 struct /* 单装 */
10 {
11 int weight, size, capability;
12 }EQUIPMENT[ 3 ];
13 struct /* 套装 */
14 {
15 int num_helm, num_armor, num_boot, capability;
16 }SET;
17 struct /* 车 */
18 {
19 int weight_limit, size_limit;
20 }CARAVAN[MAXCARAVAN];
21
22 int N, MAX_CAPABILITY;
23 char BOOT_EACH[MAXCARAVAN][MAXEQUIPMENT][MAXEQUIPMENT];
24 int PLAN[ 2 ][MAXEQUIPMENT][MAXEQUIPMENT], MAX[ 2 ][MAXCARAVAN][ 2 ];
25
26 void GET_MAX() /* 取得每辆车、前 n 辆车能单独放 helm 或 armor 的数量 */
27 {
28 int i, j;
29 for (i = 0 ; i < N; i ++ )
30 {
31 for (j = 0 ; j < 2 ; j ++ )
32 {
33 for (MAX[ 0 ][i][j] = 0 ; CARAVAN[i].size_limit >= EQUIPMENT[j].size * MAX[ 0 ][i][j] && CARAVAN[i].weight_limit >= EQUIPMENT[j].weight * MAX[ 0 ][i][j]; MAX[ 0 ][i][j] ++ )
34 ;
35 MAX[ 1 ][i][j] = MAX[ 0 ][i][j];
36 }
37 if (i > 0 )
38 for (j = 0 ; j < 2 ; j ++ )
39 MAX[ 1 ][i][j] += MAX[ 1 ][i - 1 ][j];
40 }
41 }
42 void GET_BOOT_EACH() /* 取得每辆车在存了一定数量 helm 以及 armor 后能存boot的最大数量 */
43 {
44 int helm, armor, boot, size_left, weight_left, num;
45 for (num = 0 ; num < N; num ++ )
46 {
47 for (helm = 0 ; helm < MAX[ 0 ][num][HELM]; helm ++ )
48 {
49 for (armor = 0 ; armor < MAX[ 0 ][num][ARMOR]; armor ++ )
50 {
51 size_left = CARAVAN[num].size_limit - helm * EQUIPMENT[HELM].size - armor * EQUIPMENT[ARMOR].size;
52 weight_left = CARAVAN[num].weight_limit - helm * EQUIPMENT[HELM].weight - armor * EQUIPMENT[ARMOR].weight;
53 if (size_left >= 0 && weight_left >= 0 )
54 {
55 if (BOOT_EACH[num][helm][armor] == - 1 )
56 BOOT_EACH[num][helm][armor] = 0 ;
57 while (size_left - EQUIPMENT[BOOT].size >= 0 && weight_left - EQUIPMENT[BOOT].weight >= 0 )
58 {
59 size_left -= EQUIPMENT[BOOT].size;
60 weight_left -= EQUIPMENT[BOOT].weight;
61 BOOT_EACH[num][helm][armor] ++ ;
62 }
63 }
64 }
65 }
66 }
67 }
68 void FRESH_PLAN( int index)
69 {
70 int num, helm, armor;
71 num = index % 2 ;
72 for (helm = 0 ; helm < MAXEQUIPMENT; helm ++ )
73 {
74 for (armor = 0 ; armor < MAXEQUIPMENT; armor ++ )
75 {
76 PLAN[num][helm][armor] = - 1 ;
77 }
78 }
79 }
80 void GET_PLAN( int num, int index) /* 取得前 n 辆车在放了一定量 helm 和 armor 后能放 boot 的最大数量 */
81 {
82 int helm, armor, boot, helm_pre, armor_pre;
83 if (num == 0 )
84 {
85 FRESH_PLAN(index);
86 for (helm = 0 ; helm < MAX[ 0 ][num][HELM]; helm ++ )
87 for (armor = 0 ; armor < MAX[ 0 ][num][ARMOR]; armor ++ )
88 if (BOOT_EACH[num][helm][armor] >= 0 )
89 PLAN[index % 2 ][helm][armor] = BOOT_EACH[num][helm][armor];
90 return ;
91 }
92 GET_PLAN(num - 1 , index + 1 );
93 FRESH_PLAN(index);
94 for (helm = 0 ; helm < MAX[ 0 ][num][HELM]; helm ++ ) /* 遍历从 0~MAX[0][num][]+MAX[1][num-1][] 的所有可能 */
95 {
96 for (armor = 0 ; armor < MAX[ 0 ][num][ARMOR]; armor ++ )
97 {
98 for (helm_pre = 0 ; helm_pre < MAX[ 1 ][num - 1 ][HELM]; helm_pre ++ )
99 {
100 for (armor_pre = 0 ; armor_pre < MAX[ 1 ][num - 1 ][ARMOR]; armor_pre ++ )
101 {
102 /* 看是否有效 */
103 if (BOOT_EACH[num][helm][armor] >= 0 && PLAN[(index + 1 ) % 2 ][helm_pre][armor_pre] >= 0 )
104 {
105 boot = PLAN[(index + 1 ) % 2 ][helm_pre][armor_pre] + BOOT_EACH[num][helm][armor];
106 if (PLAN[index % 2 ][helm + helm_pre][armor + armor_pre] < boot)
107 {
108 PLAN[index % 2 ][helm + helm_pre][armor + armor_pre] = boot;
109 }
110 }
111 }
112 }
113 }
114 }
115 }
116 int GET_CAPABILITY( int helm, int armor, int boot) /* 计算防御力 */
117 {
118 int set_count = 0 ;
119 while (helm - SET.num_helm >= 0 && armor - SET.num_armor >= 0 && boot - SET.num_boot >= 0 )
120 {
121 set_count ++ ;
122 helm -= SET.num_helm;
123 armor -= SET.num_armor;
124 boot -= SET.num_boot;
125 }
126 return helm * EQUIPMENT[HELM].capability + armor * EQUIPMENT[ARMOR].capability + boot * EQUIPMENT[BOOT].capability + set_count * SET.capability;
127 }
128 void CALCULATE() /* 总调用 */
129 {
130 int num, helm, armor, cur_capability;
131 for (num = 0 ; num < N; num ++ ) /* 初始化 */
132 {
133 for (helm = 0 ; helm < MAXEQUIPMENT; helm ++ )
134 {
135 for (armor = 0 ; armor < MAXEQUIPMENT; armor ++ )
136 {
137 BOOT_EACH[num][helm][armor] = - 1 ;
138 }
139 }
140 }
141 GET_MAX();
142 GET_BOOT_EACH();
143 GET_PLAN(N - 1 , 0 );
144 MAX_CAPABILITY = 0 ;
145 for (helm = 0 ; helm < MAX[ 1 ][N - 1 ][HELM]; helm ++ )
146 {
147 for (armor = 0 ; armor < MAX[ 1 ][N - 1 ][ARMOR]; armor ++ )
148 {
149 if (PLAN[ 0 ][helm][armor] >= 0 )
150 {
151 cur_capability = GET_CAPABILITY(helm, armor, PLAN[ 0 ][helm][armor]);
152 if (cur_capability > MAX_CAPABILITY)
153 {
154 MAX_CAPABILITY = cur_capability;
155 }
156 }
157 }
158 }
159 }
160
161 int main()
162 {
163 int i, count = 0 ;
164 while (scanf( " %d " , & N) && N != 0 )
165 {
166 count ++ ;
167 if (count > 1 ) putchar( 10 );
168 for (i = 0 ; i < 3 ; i ++ )
169 scanf( " %d%d%d " , & EQUIPMENT[i].weight, & EQUIPMENT[i].size, & EQUIPMENT[i].capability);
170 scanf( " %d%d%d%d " , & SET.num_helm, & SET.num_armor, & SET.num_boot, & SET.capability);
171 for (i = 0 ; i < N; i ++ )
172 scanf( " %d%d " , & CARAVAN[i].weight_limit, & CARAVAN[i].size_limit);
173 CALCULATE();
174 printf( " Case %d: %d\n " , count, MAX_CAPABILITY);
175 }
176 }
177
1、动态规划思想,最优子事件为前n-1辆车在放了一定helm和armor时能放boot的最大数量
(若用DFS全部枚举的话车一多就完全算不出来)。
2、想尽一切方法省空间,如用滚动数组(PLAN),以及把一些int的东西合理地改用char类型。
下面为DFS的代码,看着挺顺眼,也较短,但因为忽略了动态规划思想,所以超时很厉害
2
3 #define MAXCARAVAN 100
4 #define MAXPLAN 100
5 #define HELM 0
6 #define ARMOR 1
7 #define BOOT 2
8
9 struct /* 单装 */
10 {
11 int weight, size, capability;
12 }EQUIPMENT[ 3 ];
13 struct /* 套装 */
14 {
15 int num_helm, num_armor, num_boot, capability;
16 }SET;
17 typedef struct /* 安排 */
18 {
19 int helm, armor, boot;
20 }PLAN;
21 typedef struct /* 车 */
22 {
23 PLAN plan_list[MAXPLAN];
24 int plan_count;
25 int weight_limit, size_limit;
26 }CARAVAN_DEFINE;
27 CARAVAN_DEFINE CARAVAN[MAXCARAVAN];
28
29 int N, MAX_CAPABILITY;
30
31 int GET_CAPABILITY(PLAN plan)
32 {
33 int set_count = 0 ;
34 while (plan.helm - SET.num_helm >= 0 && plan.armor - SET.num_armor >= 0 && plan.boot - SET.num_boot >= 0 )
35 {
36 set_count ++ ;
37 plan.helm -= SET.num_helm;
38 plan.armor -= SET.num_armor;
39 plan.boot -= SET.num_boot;
40 }
41 return plan.helm * EQUIPMENT[HELM].capability + plan.armor * EQUIPMENT[ARMOR].capability + plan.boot * EQUIPMENT[BOOT].capability + set_count * SET.capability;
42 }
43 int CONTAINABLE( int num, PLAN plan)
44 {
45 if (CARAVAN[num].size_limit >= EQUIPMENT[HELM].size * plan.helm + EQUIPMENT[ARMOR].size * plan.armor + EQUIPMENT[BOOT].size * plan.boot
46 &&
47 CARAVAN[num].weight_limit >= EQUIPMENT[HELM].weight * plan.helm + EQUIPMENT[ARMOR].weight * plan.armor + EQUIPMENT[BOOT].weight * plan.boot)
48 return 1 ;
49 else return 0 ;
50 }
51 void GET_MAX( int num, int max[])
52 {
53 int i;
54 for (i = 0 ; i < 3 ; i ++ )
55 for (max[i] = 0 ; CARAVAN[num].size_limit >= EQUIPMENT[i].size * max[i] && CARAVAN[num].weight_limit >= EQUIPMENT[i].weight * max[i]; max[i] ++ );
56 }
57 void ADD_PLAN(PLAN * des, PLAN * ori)
58 {
59 des -> helm += ori -> helm;
60 des -> armor += ori -> armor;
61 des -> boot += ori -> boot;
62 }
63 void GET_PLAN()
64 {
65 int num, max[ 3 ];
66 PLAN plan;
67 for (num = 0 ; num < N; num ++ )
68 {
69 CARAVAN[num].plan_count = 0 ;
70 GET_MAX(num, max);
71 for (plan.helm = 0 ; plan.helm < max[HELM]; plan.helm ++ )
72 {
73 for (plan.armor = 0 ; plan.armor < max[ARMOR]; plan.armor ++ )
74 {
75 for (plan.boot = 0 ; plan.boot < max[BOOT]; plan.boot ++ )
76 {
77 if (CONTAINABLE(num, plan))
78 CARAVAN[num].plan_list[CARAVAN[num].plan_count ++ ] = plan;
79 }
80 }
81 }
82 }
83 }
84 void DFS_VISIT( int num, PLAN cur_plan)
85 {
86 int i, cur_capability;
87 PLAN pre_plan;
88 if (num == N)
89 {
90 cur_capability = GET_CAPABILITY(cur_plan);
91 if (cur_capability > MAX_CAPABILITY)
92 MAX_CAPABILITY = cur_capability;
93 return ;
94 }
95 for (i = 0 ; i < CARAVAN[num].plan_count; i ++ )
96 {
97 pre_plan = cur_plan;
98 ADD_PLAN( & cur_plan, & CARAVAN[num].plan_list[i]);
99 DFS_VISIT(num + 1 , cur_plan);
100 cur_plan = pre_plan;
101 }
102 }
103 void DFS_INI()
104 {
105 int i;
106 GET_PLAN();
107 PLAN ini_plan = { 0 , 0 , 0 };
108 MAX_CAPABILITY = 0 ;
109 DFS_VISIT( 0 , ini_plan);
110 }
111 int main()
112 {
113 int i, count = 0 ;
114 while (scanf( " %d " , & N) && N != 0 )
115 {
116 count ++ ;
117 if (count > 1 ) putchar( 10 );
118 for (i = 0 ; i < 3 ; i ++ )
119 scanf( " %d%d%d " , & EQUIPMENT[i].weight, & EQUIPMENT[i].size, & EQUIPMENT[i].capability);
120 scanf( " %d%d%d%d " , & SET.num_helm, & SET.num_armor, & SET.num_boot, & SET.capability);
121 for (i = 0 ; i < N; i ++ )
122 scanf( " %d%d " , & CARAVAN[i].weight_limit, & CARAVAN[i].size_limit);
123 DFS_INI();
124 printf( " Case %d: %d\n " , count, MAX_CAPABILITY);
125 }
126 }
127