2013-09-11 07:58:35Morris

[UVA][剪枝] 1240 - ICPC Team Strategy

ICPC (International Collegiate Programming Contest), as you might know, is a team programming contest for college students. Each team consists of exactly three students and they will work on a number of programming problems.

Andi, Budi and Chandra plan to participate in this year ICPC as a team. As for their team strategy, they come up with a simple one:

  • In the first 20 minutes of 5 hours contest, they will read through all problems. Then each of them will assign a number to each problem. This number indicates how many minute(s) it will take for him to get the problem accepted (correct solution). Then they will start to code, meaning that they only have 280 minutes to really work on the problems. You may assume that they always get accepted on time whenever they work on a problem.
  • There's only one computer for each team, so it's not possible for them to code two different problems simultaneously.
  • To avoid any brain fatigue and adrenaline rush (because they attend competitions so frequently), they decided to switch role after each problem, such that none of them will work at the computer for more than one problem consecutively.
  • They want to solve as many problems as they can. The order of problem to be solved does not matter.

Input 

The first line of input contains an integer T , number of test cases to follow. Each case begins with an integer N (1$ le$N$ le$12) in one line, denoting the number of problems. The second line contains N integers, A1..N (1$ le$Ai$ le$300) , denoting the total time (in minutes) needed by Andi to solve ith problem. The third and fourth line will correspond to the total time needed by Budi and Chandra respectively and will have the same input format as the second line.

Output 

For each case, print in a single line containing the maximum total number of problem that can be solved by that team.


Explanation for 1st sample case:

Actually Andi could solve all the three problems alone, but the team has decided that none of them should work at the computer for more than one problem consecutively.


Explanation for 2nd sample case:

The team can solve all the problems. Here is one solution:

  • Let Budi work on Problem-2 (100 minutes).
  • Switch to Andi and let him work on Problem-1 (50 minutes).
  • Switch to Budi again and let him work on Problem-3 (30 minutes).
  • Finally, switch to Chandra and let him work on Problem-4 which (100 minutes).

Overall, they need 100 + 50 + 30 + 100 = 280 minutes.

Sample Input 

2 
3 
100 100 80 
190 120 90 
120 150 100 
4 
50 20 300 300 
200 100 30 250 
140 120 100 100

Sample Output 

2 
4

題目描述:

在 5 個小時的比賽中,由 3 位選手輪流解題(因為一個人連續解 2 題會壞掉)。
而每個人做題所消耗的時間也會有所不同。

現在有 n 道題目,問在輪流解題的情況下,280 分鐘內最多能解出多少題目。
(前 20 分鐘進行看題估算每個人消耗的時間)。

題目解法:

窮舉的時候,不必窮舉排列。

考慮窮舉分配的題目,因此每個搜索狀態為 dfs(i, a, b, c, time)

當前窮舉分配了 i 題,分別做了 a 題, b 題, c 題,總計花費時間 time

而在最後檢查是否能使用輪流的方式進行分配,即相對於看一個人解的題數,是否有足夠的空隙塞入。

而剪枝就相對簡單了,從搜索狀態中下手 dp[i][a][b][c] 的最少時間!

因為最後我們只看 a+b+c 的最大值,較大的時間肯定是多餘的解。

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int A[15], B[15], C[15], n;
int dp[15][15][15][15];
int ret;
void dfs(int idx, int a, int b, int c, int time) {
if(time > 280)
return;
if(dp[idx][a][b][c] <= time)
return;
dp[idx][a][b][c] = time;
if(c <= a+b+1 && b <= a+c+1 && a <= b+c+1)
ret = max(ret, a+b+c);
if(idx == n)
return;
dfs(idx+1, a+1, b, c, time+A[idx]);
dfs(idx+1, a, b+1, c, time+B[idx]);
dfs(idx+1, a, b, c+1, time+C[idx]);
dfs(idx+1, a, b, c, time);
}
int main() {
int testcase;
int i, j, k;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d", &A[i]);
for(i = 0; i < n; i++)
scanf("%d", &B[i]);
for(i = 0; i < n; i++)
scanf("%d", &C[i]);
ret = 0;
memset(dp, 63, sizeof(dp));
dfs(0, 0, 0, 0, 0);
printf("%d\n", ret);
}
return 0;
}