最大映射

    有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
    输入描述:每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串。 n 不大于 50,且至少存在一个字符不是任何字符串的首字母。
    输出描述:输出一个数,表示最大和是多少。
    输入例子:
    2
    ABC
    BCA
    输出例子:
    1875
    解析:给大写字母A~J中的每一个字母赋一个权重,按照权重由大到小进行排序,依次把9~0十个数字赋值给排序好的的字母。问题的关键就在于我们如何给字母赋值权重。假如我们有字符串"ABCD",我们从低位到高位依次给每个字母赋值为1,10,100,1000...等。w(D) = 1,w(C) = 10,w(B) = 100,w(A) = 1000。最后我们把输入字符串中的每个字符的权重相加。比如字符串"ABC"和字符串"BCA"。赋值及求和如下图所示:

    因为字符串映射为的整数不存在前导零,所以我们需要做一步特殊的处理,在每个字符串首位置出现的字符都不能为零。如果出现这种情况,我们需要把不在首尾出现的具有最小权值字符提到排好序的数组的首部。
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<numeric>
using namespace std;

//节点类:每个字符对应一个权重
struct Node
{
	char ch;
	long long num;
	Node(){}
	Node(char c, int n) :ch(c), num(n)
	{

	}
};

//按照权重对节点进行排序
bool cmp(const Node &lh, const Node &rth)
{
	return lh.num < rth.num;
}

//取得每个字符的权重
void getNum(vector<string> &data, vector<Node> &arr)
{
	for (int i = 0; i < data.size(); ++i)
	{
		long long index = 1;
		for (int j = data[i].size() - 1; j >= 0; --j)
		{
			int pos = data[i][j];
			arr[pos - 'A'].num += index;
			index *= 10;
		}
	}
}

int main(void)
{
	int n;
	while (cin >> n)
	{
		string str;
		//字符串集合
		vector<string> data(n);
		for (int i = 0; i < n; ++i)
		{
			cin >> str;
			data[i] = str;
		}
		//节点类集合
		vector<Node> arr(10);
		for (int i = 'A'; i <= 'J'; ++i)
		{
			arr[i - 'A'] = Node(i, 0);
		}
		//计算每个字符的权重
		getNum(data, arr);
		//按照权重由小到大进行排序
		sort(arr.begin(), arr.end(), cmp);
		//每个字符是否在字符串首位置出现过(1:出现过)
		vector<int> isFlag(10, 0);
		for (int i = 0; i < n; ++i)
		{
			isFlag[data[i][0] - 'A'] = 1;
		}
		//在排序数组中,第一个没有在字符串首位置出现的字符的位置
		int pos = 0;
		for (; pos < 10; ++pos)
		{
			if (isFlag[arr[pos].ch - 'A'] == 0)
				break;
		}
		Node tmp = arr[pos];
		//向后移动一位,把pos位置的元素放在首部
		for (int i = pos; i > 0; --i)
		{
			arr[i] = arr[i - 1];
		}
		arr[0] = tmp;
		//0~9赋值给相应的字符
		vector<int> numArr(10);
		for (int i = 0; i < 10; ++i)
		{
			numArr[arr[i].ch - 'A'] = i;
		}
		//字符串集合转换为整型数集合
		vector<long long> num(n);
		for (int i = 0; i < n; ++i)
		{
			long long val = 0;
			long long index = 1;
			for (int j = data[i].size() - 1; j >= 0; --j)
			{
				val += numArr[data[i][j] - 'A'] * index;
				index *= 10;
			}
			num[i] = val;
		}
		long long count = 0;
		//对整型数集合求值
		cout << accumulate(num.begin(), num.end(), count) << endl;
	}
	system("pause");
	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值