uva 11372 Arranging a Contest(DP)

ProblemB: Arranging a Contest


Today is 29 November, 2007.

A month later, we will have our traditional Contest of Newbies 2007, so it is time for the Newbie Problemsetters (NPS) to come up with the programming tasks. This year, due to heavy schoolwork, NPS fail to write six brand-new tasks for the contest. Luckily, they have a question bank with many good programming tasks. NPS just have to pick six of the tasks out from there. The question is: which six?

A newbies contest should be easy enough so that even a beginner is able to solve a couple of tasks for rewarding sake. At the same time, there should be some harder ones to satisfy the needs of other more experienced contestants. To make the contest more interesting, the tasks should be of various types.

For each problem in the question bank, NPS have assigned a "difficulty level" and a "favour index". The problems are of course on different topics, including dynamic programming (DP), simple mathematics, graph theory etc. NPS would like to choose the tasks such that:

  • There are exactly 2 easy tasks and exactly 2 hard ones; and
  • There are at least 2 DP tasks, at least 1 graph problem, and at least 1 about maths; and
  • The total "favour indices" is then to be maximized.

Can you write a program to help them?

Input

The input file consists of several test cases. The first line of each case contains an integer N (6 ≤ N ≤ 200), the number of tasks in the question bank. Then there are N lines, each corresponding to one task in the question bank. See figure below:

The input file is terminated by a line with only the number 0.

Output

For each case, if it is not possible to satisfy the requirements, print "No solution." (without the quotes). Otherwise, print the ID's of the six problems that NPS should choose. If there are more than one solutions, print the lexicographically smallest one (i.e. treat the output line as a string and consider its ASCII value).

Sample Input

7
000 SIMPLIFYING_FRACTIONS____ M M 2
001 ARRANGING_A_CONTEST______ E X 1
002 TRAVEL_IN_DESERT_________ M G 5
003 LONGEST_PALINDROME_______ E D 4
004 HEADMASTER'S_HEADACHE____ H D 4
005 ANDY'S_FIRST_DICTIONARY__ E X 4
006 POWER_OF_MATRIX__________ H M 3
0

Sample Output

000 002 003 004 005 006

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace  std;

const int maxn = 210;
struct Problem{
	string ID;
	char level;
	char type;
	int favor;
}p[maxn];
struct Dp{
	string ans;
	int sum;
	Dp(string st = "" , int s = 0){
		ans = st , sum = s;
	}
}dp[maxn][7][3][3][5][4][4];
int n;

bool cmp(Problem p1 , Problem p2){
	return p1.ID < p2.ID;
}

void initial(){
	for(int i = 0;i < maxn;i++){
		for(int j = 0;j < 7;j++){
			for(int k = 0;k < 3;k++){
				for(int l = 0;l < 3;l++){
					for(int a = 0;a < 5;a++){
						for(int b = 0;b < 4;b++){
							for(int c = 0;c < 4;c++){
								dp[i][j][k][l][a][b][c].ans = "";
								dp[i][j][k][l][a][b][c].sum = -1;
							}
						}
					}
				}
			}
		}
	}
}

void readcase(){
	string name;
	for(int i = 0;i < n;i++){
		cin >> p[i].ID >> name >> p[i].level >> p[i].type >> p[i].favor;
	}
}

Dp DP(int N , int remain , int easy , int mid , int D , int M , int G){
	if(n-N < remain) return dp[N][remain][easy][mid][D][M][G] = Dp("" , 0);
	if(remain == 0){
		if(easy == 2 && mid == 2 && D >= 2 && M >= 1 && G >= 1) return dp[N][remain][easy][mid][D][M][G] = Dp("" , 1);
		return dp[N][remain][easy][mid][D][M][G] = Dp("" , 0);
	}
	if(easy > 2 || mid > 2 || D > 4 || M > 3 || G > 3) return dp[N][remain][easy][mid][D][M][G] = Dp("" , 0);
	if(dp[N][remain][easy][mid][D][M][G].sum != -1) return dp[N][remain][easy][mid][D][M][G];
	Dp temp , tt;
	int te = easy, tm = mid , tD = D, tM = M, tG = G;
	if(p[N].level == 'E') te++;
	if(p[N].level == 'M') tm++;
	if(p[N].type == 'D') tD++;
	if(p[N].type == 'M') tM++;
	if(p[N].type == 'G') tG++;
	tt = DP(N+1 , remain-1 ,te , tm , tD , tM , tG);
	if(tt.sum > temp.sum){
		temp.sum = tt.sum+p[N].favor;
		if(tt.ans == ""){
			temp.ans = p[N].ID;
		}else{
			temp.ans = p[N].ID+" "+tt.ans;
		}
	}
	tt = DP(N+1 , remain , easy , mid , D , M , G);
	if(tt.sum > temp.sum){
		temp.sum = tt.sum;
		temp.ans = tt.ans;
	}
	return dp[N][remain][easy][mid][D][M][G] = temp;
}

void computing(){
	sort(p , p+n , cmp);
	Dp tem = DP(0 , 6 ,0 , 0 , 0 , 0 , 0);
	if(tem.sum == 0){
		printf("No solution.\n");
	}else{
		cout << tem.ans << endl;
	}
}

int main(){
	//freopen("in" , "r" , stdin);
	while(cin >> n && n){
		initial();
		readcase();
		computing();
	}
	return 0;
}

 

Problemsetter: Mak Yan Kei
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值