题意
题目的意思是给顾客提供他需要的面值的邮票,需要满足三个条件,种类尽可能多,数量尽可能少,最大面值尽可能大。
分析
对于多种情况,对种类,数量,最大面值赋予不同的权值,可以免去三次判断,比如选择100 * types-10 * count + value更大的情况即可。同种面值的种类超过5时,多余的可以略去,不影响结果。
注意输入时相同面值的邮票属于不同种类,另外邮票种类并不止25种(坑)。
深度搜索搞定。
代码如下:
Memory: 252K Time: 0MS Length:105LINES
#include<iostream>
using namespace std;
void Copy(int* s, int* d) { for (int i = 0; i < 4; ++i) d[i] = s[i]; }
int vecstamp0[66] = {};
void sort(int* vecstamp, int& stamptypes)
{
for (int i = 0; i < stamptypes; ++i) //冒泡排序
for (int j = i + 1; j < stamptypes; ++j)
if (vecstamp[j] < vecstamp[i]) swap(vecstamp[j], vecstamp[i]);
int count = 0;
for (int i = 0; i < stamptypes; ++i) //超过5种的略去
{
int len = 0;
int j = i;
for (; j < stamptypes - 1; ++j)
{
if (len < 5) vecstamp0[count++] = vecstamp[i];
if (vecstamp[i] == vecstamp[j + 1]) ++len;
else break;
}
i = j;
}
vecstamp0[count++] = vecstamp[stamptypes - 1];
stamptypes = count;
}
int bestTypes = 0; //当前最优种类数
int bestCount = 0; //当前最优数量
int types = 0; //已经选择的种类
int maxvalue = 0; //已经选择的最大面值
int stamptypes = 0; //邮票的种类
bool Select(int* vecstamp, int* selected, int sum, int count, int& require, int& maxGrade, int& sign, int* bestGroup, int prepos)
{
if (sum > require) return false; //面值和已经超出时,返回false
else if (sum == require)
{
int types = 0;
for (int i = 0; i < count; ++i)
{
while (i < count - 1 && selected[i + 1] == selected[i]) ++i; //计算已经选择的种类
++types;
}
int grade = 100 * types - 10 * count + maxvalue;
if (grade > maxGrade)
{
sign = 1; //已经有解
bestTypes = types;
bestCount = count;
Copy(selected, bestGroup);
maxGrade = grade;
}
else if (grade == maxGrade) ++sign; //重复的最优解
return true;
}
else
{
if (count == 4) return true;
for (int pos = prepos; pos < stamptypes; ++pos) //prepos保证搜索是从当前位置开始往后搜
{
maxvalue = vecstamp[pos]; //邮票面值已经排序,所以当前选择邮票的面值必然是最大值
selected[count] = pos;
bool s = Select(vecstamp, selected, sum + vecstamp[pos], count + 1, require, maxGrade, sign, bestGroup, pos);
selected[count] = -1; //恢复状态
maxvalue = vecstamp[prepos];
if (s) continue;
else break;
}
--types;
return true;
}
}
int main()
{
int vecstamp[66] = {};
while (stamptypes < 66 && cin >> vecstamp[stamptypes])
{
if (vecstamp[stamptypes] == 0)
{
sort(vecstamp, stamptypes);
int require = 0;
while (cin >> require && require != 0)
{
int maxGrade = 0;
int sign = 0;
int bestGroup[4] = {};
types = 0;
maxvalue = 0;
int selected[4];
selected[0] = selected[1] = selected[2] = selected[3] = -1;
Select(vecstamp0, selected, 0, 0, require, maxGrade, sign, bestGroup, 0);
if (sign > 1) cout << require << " (" << bestTypes << "): tie" << endl;
else if (sign == 1)
{
cout << require << " (" << bestTypes << "):";
for (int j = 0; j < bestCount; ++j) cout << " " << vecstamp[bestGroup[j]];
cout << endl;
}
else cout << require << " ---- none" << endl;
}
stamptypes = 0;
continue;
}
++stamptypes;
}
return 0;
}