有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
输入描述:
每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串。 n 不大于 50,且至少存在一个字符不是任何字符串的首字母。
输出描述:
输出一个数,表示最大和是多少。
输入例子1:
2 ABC BCA
输出例子1:
1875
如题所示:可以根据权值大小来赋予字母的值,例如在这题中:
ABC=100×A+10×B+C
BCA=100×B+10×C+A
则ABC+BCA=110×B+101×A+11×C(根据权值从大到小排序)。
要使和最大,那么权值大的,对应的值就应该越大,B为9, A为8,C为7,可算得结果为:1875。
根据以上方法,可以用一个数组保存对应的权值,进行简单排序,然后根据排序的大小,进行赋值求结果;注意,题目中还要求不能有前导零,我们可以设置一个标识,当每项的第一位,就将其标识为1,表示这是不能为零;当它为数组的最小时,则要将其与前面可以为0的交换位置,例如:
A 100 1
J 11 1
C 10 0
D 9 0
E 8 1
B 7 0
G 6 0
H 5 1
I 4 1
F 3 1
此处的F的标识位为1,表示其不能为0,则需要寻找其前面可以为0的项,很明显G 6 0这项,标识位为0,将G 6 0放到末尾去,变成:(H 5 1 和 I 4 1 这两项都标识位都为1,不能放在尾部)
A 100 1
J 11 1
C 10 0
D 9 0
E 8 1
B 7 0
H 5 1
I 4 1
F 3 1
G 6 0
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct WeightInt
{
long w;
int flag;
}wi[10];
int n;
bool compare(WeightInt a, WeightInt b) //以从小到大的方式排序
{
return a.w < b.w;
}
int main()
{
cin>>n;
string s;
for(int i = 0; i < n; i++)
{
cin >> s;
long base = 1;
for(int j = s.size()-1; j >= 0; j--, base *= 10)
{
int idx = s[j] - 'A';
if(j == 0) wi[idx].flag = 1;
wi[idx].w += base;
}
}
sort(wi, wi+10, compare);
if(wi[0].flag == 1)
{
int k = 0;
for( ; k < 11; k++)
if(wi[k].flag == 0)
break;
WeightInt tmp = wi[k];
for(;k>0; k--)
wi[k] = wi[k-1];
wi[0] = tmp;
}
long sum = 0;
for(int i = 9; i >= 0; i--)
{
sum += wi[i].w*i;
}
cout << sum << endl;
return 0;
}