//用MT[k][n][v] (k>=0, 0<=n<=4, v>=0) 表示从前k个类型中,最多取n张,总面值为v的所有组合中最大的类型数。则有递推方程:
//MT[k][n][v] = MAX{ MT[k-1][n-i][v-i*Values[k-1]] + (i>0?1:0) } (0<=i<=n, v>=i*Values[k-1])
#include<iostream>
#include<cstdio>
#include<climits>
using namespace std;
#define STAMP_ARR_L 100
#define COMB_ARR_L 4
int s_arr[STAMP_ARR_L], s_cnt, customer;//邮票类型数组、邮票类型数目、顾客需求
int best_comb_p[COMB_ARR_L], max_type, min_num, max_val, flag_tie;//最佳组合、最大类型数、最小邮票数、最大单面值
int comb_p[COMB_ARR_L], m_t, m_n, m_v, sum;//当前枚举组合、类型数、邮票数、最大面值
void sort(int arr[], int &cnt){
int i, j, k, last;
for (i = 0; i < cnt - 1; i++)
for (j = cnt - 1; j > i; j--)
if (arr[j] < arr[j - 1])
arr[j] ^= arr[j - 1] ^= arr[j] ^= arr[j - 1];
i = 0; j = 0; last = -1;
while (j < cnt){//当同面值邮票多于5张时没有用
if (arr[j] == last){
if (k == 5){
j++;
} else{
arr[i++] = arr[j++];
k++;
}
} else{
last = arr[j];
arr[i++] = arr[j++];
k = 1;
}
}
cnt -= j - i;
}
void updateBestComb(int num){
int i, j;
m_n = COMB_ARR_L - num;
for (i = 1, j = 1; i < m_n; i++)
if (comb_p[i] != comb_p[i - 1])
j++;
m_t = j;
m_v = comb_p[m_n - 1];
if (m_t == max_type && m_n == min_num && m_v == max_val) flag_tie = 1;
if ((m_t > max_type) ||
(m_t == max_type && m_n < min_num) ||
(m_t == max_type && m_n == min_num && m_v > max_val)){
for (i = 0; i < m_n; i++) best_comb_p[i] = comb_p[i];
max_type = m_t;
min_num = m_n;
max_val = m_v;
flag_tie = 0;
}
}
//在邮票数组s_arr中,从s_arr_p位置开始,向后选择num张邮票,使其总面值为customer
void findBestComb(int s_arr_p,int customer,int num){
if (customer == 0 && s_arr_p < s_cnt && num >= 0){
updateBestComb(num);
} else if (customer > 0 && num > 0){
for (int i = s_arr_p; i < s_cnt; i++){
comb_p[COMB_ARR_L - num] = i;
findBestComb(i, customer - s_arr[i], num - 1);
}
}
return;
}
int main(){
while (true){
s_cnt = 0;
while (cin >> s_arr[s_cnt], s_arr[s_cnt]) s_cnt++;
if (cin.fail()) break;
sort(s_arr, s_cnt);
while (cin >> customer, customer){
max_type = 0; min_num = INT_MAX; max_val = 0; sum = 0; flag_tie = 0;
findBestComb(0, customer, COMB_ARR_L);
if (max_type == 0){
printf("%d ---- none\n", customer);
} else if (flag_tie){
printf("%d (%d): tie\n", customer, max_type);
} else{
printf("%d (%d):", customer, max_type);
for (int i = 0; i < min_num; i++)
printf(" %d", s_arr[best_comb_p[i]]);
printf("\n");
}
}
}
return 0;
}
//暴搜版本
#include<iostream>
#include<cstdio>
#include<climits>
using namespace std;
void sort(int arr[], int &cnt){
int i, j, k, last;
for (i = 0; i < cnt - 1; i++)
for (j = cnt - 1; j > i; j--)
if (arr[j] < arr[j - 1])
arr[j] ^= arr[j - 1] ^= arr[j] ^= arr[j - 1];
i = 0; j = 0; last = -1;
while (j < cnt){//当同面值邮票多于5张时没有用
if (arr[j] == last){
if (k == 5){
j++;
} else{
arr[i++] = arr[j++];
k++;
}
} else{
last = arr[j];
arr[i++] = arr[j++];
k = 1;
}
}
cnt -= j - i;
}
int main(){
int s_arr[100], s_cnt, customer;//邮票类型数组、邮票类型数目、顾客需求
int best_comb[4], max_type, min_num, max_val, flag_tie;//最佳组合、最大类型数、最小邮票数、最大单面值
int m_t, m_n, m_v, sum;//当前枚举情况下的类型数、邮票数、最大面值
int i, j, k, l;
while (true){
s_cnt = 0;
while (cin >> s_arr[s_cnt], s_arr[s_cnt]) s_cnt++;
if (cin.fail()) break;
sort(s_arr, s_cnt);
while (cin >> customer, customer){
max_type = 0; min_num = INT_MAX; max_val = 0; sum = 0; flag_tie = 0;
//枚举所有情况
for (i = 0; i <= s_cnt; i++)
for (j = i; j <= s_cnt; j++)
for (k = j; k <= s_cnt; k++)
for (l = k; l <= s_cnt; l++){
m_t = 0; m_n = 0; m_v = 0; sum = 0;
if (i < s_cnt){
m_t++;
m_n++;
m_v = s_arr[i];
sum += s_arr[i];
if (j < s_cnt){
if (j != i) m_t++;
m_n++;
m_v = s_arr[j];
sum += s_arr[j];
if (k < s_cnt){
if (k != j) m_t++;
m_n++;
m_v = s_arr[k];
sum += s_arr[k];
if (l < s_cnt){
if (l != k) m_t++;
m_n++;
m_v = s_arr[l];
sum += s_arr[l];
}
}
}
}
if (sum == customer){
if (m_t == max_type && m_n == min_num && m_v == max_val) flag_tie = 1;
if ((m_t > max_type) ||
(m_t == max_type && m_n < min_num) ||
(m_t == max_type && m_n == min_num && m_v > max_val)){
best_comb[0] = s_arr[i];
best_comb[1] = s_arr[j];
best_comb[2] = s_arr[k];
best_comb[3] = s_arr[l];
max_type = m_t;
min_num = m_n;
max_val = m_v;
flag_tie = 0;
}
} else continue;
}
if (max_type == 0){
printf("%d ---- none\n", customer);
} else if (flag_tie){
printf("%d (%d): tie\n", customer, max_type);
} else{
printf("%d (%d):", customer, max_type);
for (i = 0; i < min_num; i++)
printf(" %d", best_comb[i]);
printf("\n");
}
}
}
return 0;
}