题目一
描述
有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
输入描述
每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串。 n 不大于 50,且至少存在一个字符不是任何字符串的首字母。
输出描述
输出一个数,表示最大和是多少。
输入例子
2
ABC
BCA
输出例子
1875
思路
这道题首先把输入字符串看作十进制数,以输入例子为例,即 ABC = 100 * A + 10 * B + 1 * C, BCA = 100 * B + 10 * C + 1 * A
,则它们的和为 ABC + BCA = 110 * B + 101 * A + 11 * C
(按系数大小降序排列),由此可知系数较大的字符应映射较大的数字,这里可取 B = 9, A = 8, C = 7
,得到结果1875。此外应注意按系数排序后的首个字符可能映射为 0 的情况,此时应把该字符替换为最近的映射为非 0 的字符,其余各项向后移动填充空缺。
代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool comparator(const pair<uint64_t, bool>& lhs, const pair<uint64_t, bool>& rhs) {
return lhs.first < rhs.first;
}
uint64_t maxNum(vector<string>& strs) {
vector<pair<uint64_t, bool>> memo(10, make_pair(0, false));
for (auto& s : strs) {
uint64_t digit = 1;
for (int i = s.size() - 1; i >= 0; --i) {
memo[s[i] - 'A'].first += digit;
if (i == 0) memo[s[i] - 'A'].second = true;
digit *= 10;
}
}
sort(memo.begin(), memo.end(), comparator);
uint64_t res = 0;
if (memo[0].second) {
int firstNoZero = 1;
while (memo[firstNoZero].second) {
++firstNoZero;
}
auto tmp = memo[firstNoZero];
for (uint64_t i = firstNoZero; i > 0; --i) {
memo[i] = memo[i - 1];
}
memo[0] = tmp;
}
for (uint64_t i = 0