有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?
每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串。 n 不大于 50,且至少存在一个字符不是任何字符串的首字母。
输出一个数,表示最大和是多少。
2 ABC BCA
1875
<简单代码, 一看就懂> STL只用vector
#include <iostream> #include <vector> #include <algorithm> #include <string> #include <cmath> using namespace std; typedef unsigned long long ULL; ULL maxPrj(const vector<string> &sv){ ULL max_sum = 0; vector<vector<ULL> > W (10,vector<ULL>(2,0)); /** Calculate the W of each character **/ for(int i=0; i<sv.size(); i++){ //Highest digit, mark it with 1, meaning 'it can't be 0' W[ sv[i][0]-'A' ][1] = 1; for(int j=0; j<sv[i].size(); j++){ W[ sv[i][j]-'A' ][0] += pow(10, sv[i].size()-j-1); } } /** Generate coding strategy **/ sort(W.begin(), W.end(), [](const vector<ULL> &a, const vector<ULL> &b){return a[0]>b[0];} ); //【Handle special cases】 int k; if( W.back()[1] == 1){ // Start from the last elem, find the smallest weight with the mark 0 for(k=W.size()-1; W[k][1] == 1; k--); // Set this character to 0 (=Erase this elem) W.erase(W.begin()+k); } //Calculate max_sum for(int i=0; i<W.size(); i++){ if( W[i][0] != 0 ) max_sum += W[i][0]*(9-i); else break; } return max_sum; } int main(){ int n; cin>>n; cin.ignore(); vector<string> sv = vector<string> (n); for(int i=0; i<n; i++) getline(cin, sv[i]); cout << maxPrj(sv); return 0; }
#include <bits/stdc++.h> using namespace std; vector<string> v; vector<char> helper = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; int zero[26]; unsigned long long get_sum(unordered_map<char, int> mp, int i = 0){ unsigned long long sum = 0; if (i == v.size()) return sum; for (auto &ch : v[i]) sum = sum * 10 + mp[ch]; return sum + get_sum(mp, i + 1); } int cmp(char x, char y){ return get_sum({{x, 1}, {y, 2}}) < get_sum({{x, 2}, {y, 1}}); } int main(){ string temp; unordered_map<char, int> mp; //最终的映射结果 int n; cin >> n; for (int i = 0; i < n; i++) { cin >> temp; zero[temp[0] - 'A'] = 1; //首字母不能为0,标记左右首字母 v.push_back(temp); } sort(helper.begin(), helper.end(), cmp); //排序 if (zero[helper.back() - 'A']) { //当最后一个字符不应该为0时, for (int i = (int)helper.size() - 1; i >= 0; i--){ if (zero[helper[i] - 'A'] == 0) { //找到一个可以为0的字符z位置i helper.push_back(helper[i]); //将helper[i]放到末尾,让他为0 helper.erase(helper.begin() + i); //删除多余的helper[i] break; } } } for (int i = 0; i < (int)helper.size(); i++) { //构建目的映射 mp[helper[i]] = 9 - i; } cout << get_sum(mp) << endl; //计算结果 return 0; }
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n;
while(s.hasNext()){
n = s.nextInt();
String[] str = new String[n];
Element[] e = new Element[10];
for(int i=0;i<10;i++){
e[i] = new Element();
}
for(int i=0;i<n;i++){
str[i] = s.next();
int l=str[i].length();
long base = 1;
for(int j=l-1;j>=0;j--){
int idx=str[i].charAt(j)-'A';
//如果该字母出现在首部,则标记为不能为0;即flag标记为false
if(j==0){
e[idx].flag=false;
}
e[idx].weight+=base;
base*=10;
}
}
Arrays.sort(e, new Comparator<Element>() {
@Override
public int compare(Element o1, Element o2) {
return o1.weight>o2.weight?1:(o1.weight==o2.weight?0:-1);
}
});
long sum = 0;
//权值最低且不能为0的情况
if(!e[0].flag){
int k=0;
for(;k<10;k++){
if(e[k].flag){
break;
}
}
Element tmp=e[k];
for(;k>0;k--){
e[k]=e[k-1];
}
e[0]=tmp;
}
//权值越大映射的值越大
for(int i=9;i>=0;i--){
sum+=e[i].weight*i;
}
System.out.println(sum);
}
}
static class Element{
//表示权值
long weight=0;
//表示该字母是否可以为0 false表不可以为0;true表可以为0
boolean flag=true;
}
}
#include <iostream> #include <algorithm> #include <string> #include <vector> #include <math.h> #include <assert.h> #include <cstring> using namespace std; typedef unsigned long long ULL; // 最大要计算 12 位的正整数,所以还是用一个大点的类型吧 // 依据权重表 weight, 得到映射表 ret (即: 排位) // 比如: // // | table | A | B | C | D | E | F | G | H | I | J | // |-------|--------|----------|----|--------|-------|------|---|-----|-----|------| // | weight|10000001| 1010001 | 20 | 100000 | 10000 | 1000 | 1 | 100 | 110 | 1000 | // |-------|--------|----------|----|--------|-------|------|---|-----|-----|------| // | ret | 9 | 8 | 1 | 7 | 6 | 5 | 0 | 2 | 3 | 4 | // void map_weight(ULL* weight, int* ret, const int n = 10) { // // 排位算法: // 初值都为 9 // C(10, 2) : 从10个数中挑选两个数。 // 比较这两个数:谁小谁减一,相等的话随便挑选一个减一 // assert(n == 10); for (int i = 0; i < n; ++i) { ret[i] = 9; } for (int i = 0; i < n; ++i) { if (weight[i] == 0) { ret[i] = 0; continue; } for (int j = i + 1; j < n; ++j) { if (weight[j] == 0) { ret[j] = 0; continue; } if (weight[i] < weight[j]) { ret[i]--; } else { ret[j]--; } // 因为映射不能重复, // 所以当 weight[i] == weight[j] 权重相等时, // 随意挑选一个减一即可。 // 例如: 'A' 和 'B' 权重值相等,但不能都映射为 9 // 此时,随意挑选一个使其映射值 减一 即可 9, 8 } } } // 判断给定的字符 c 是否在 input 中有作为首字符出现 bool is_header(const char c, const vector<string>& input) { const size_t len = input.size(); for (size_t i = 0; i < len; ++i) { if (c == input[i][0]) return true; } return false; } // 依据给定的值,在映射表 ret 中查找对应的下标 (可进一步优化) int get_pos(const int value, const int* ret, const int n = 10) { for (int i = 0; i < n; ++i) { if (value == ret[i]) return i; } return -1; } // 因为不能有 0 开头的数字,所以要修正一下映射表 ret void fixed_ret(int *ret, char *table, const vector<string>& input, const int n = 10) { int pos_0 = get_pos(0, ret); assert(pos_0 >= 0); if (! is_header(table[pos_0], input)) return; // 当前序列需调整 // 依次查找 最小非开头的映射值 i int opt_pos = -1; for (int i = 1; i < n; ++i) { int pos = get_pos(i, ret); assert(pos >= 0); if (! is_header(table[pos], input)) { // 找到了最小的不是 table[pos] 打头的值 i 了 // 记下下标即可 opt_pos = pos; break; } } if (opt_pos == -1) { // 没有找到合适的值。(用例有问题) return; } // 调整开始 // 比 ret[opt_pos] 小的值都加1,最后再将 ret[opt_pos] 置 0 for (int i = 0; i < n; ++i) { if (ret[i] < ret[opt_pos]) { ret[i]++; } } ret[opt_pos] = 0; } template<typename T> void show(const T& arr) { for (auto& v : arr) { cout << v << ' '; } cout << endl; } void check(const string& input_str) { for (auto& s : input_str) { assert(s >= 'A' && s <= 'J'); } } int main() { int n; cin >> n; assert(n > 0 && n <= 50); vector<string> input(n); for (int i = 0; i < n; ++i) { cin >> input[i]; const size_t len = input[i].size(); assert(len <= 12); check(input[i]); } // 输入完毕,并完成合法性检查 char table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; ULL weight[10] = {0}; // 权重表:A - J 每个字母的权重 // 遍历 input[], 统计权重 // 算法: // // 设 // 个位权值 为 1 // 十位权值 为 10 // 百位权值 为 100 // 依次类推, 没有出现的字母权值为 0 // // 统计每个字母的累计权重值 // // 例如输入两组数据: // // ABC // BCA // // 则 A 的权重为 100 + 1 = 101 // B 的权重为 10 + 100 = 110 // C 的权重为 1 + 10 = 11 // D - J 的权重为 0 // // for (int i = 0; i < n; ++i) { ULL w = pow(10, input[i].size() -1); for (auto& v : input[i]) { weight[v - 'A'] += w; w /= 10; } } #ifdef DEBUG cout << endl << "weight = "; show(weight); #endif //DEBUG // 依据权重高低依次映射 9 ~ 0 // // 将统计而来的 权重表进行 排位,最高权重的映射为 9, // 最小权重的映射为 0。 int ret[10]; map_weight(weight, ret, 10); #ifdef DEBUG cout << "ret = "; show(ret); #endif //DEBUG // 修正 映射表, 因为 不能有 0 开头的数字 // // 算法:检查当前映射表中 ret ,映射为 0 的字母是否在 input 中打头 // 若不打头什么也不做; // 若打头,则将不打头的最小映射值 变更为 0, // 比刚才发现的最小映射值小的所有映射值加 1 // // 比如 映射表为 9 1 0 7 8 6 2 5 4 3 // 此时 0 对应的字母是 talble[2] 即 'C' // 如果 'C' 有当过头字母,则需要修正映射表, // 再如, 'B' 也出现过打头,但 'G' 没有出现过打头的情况,则映射表修正如下 // 9 2 1 7 8 6 0 5 4 3 // fixed_ret(ret, table, input); #ifdef DEBUG cout << "after fixed:\nret = "; show(ret); #endif //DEBUG // 计算结果 // // 将 (权重表 x 映射表),然后再累加起来就是题目要的答案 // // 例如 // // 输入例子: // ABC // BCA // // 设 table = A B C D E F G H I J // // 则 // 权重表 // weight = 101 110 11 0 0 0 0 0 0 0 // 进而得到 // 映射值 // ret = 8 9 7 0 0 0 0 0 0 0 // // 则这些数的和为 // // (101 * 8) + (110 * 9) + (11 * 7) = 1875 // ULL sum = 0; for (int i = 0; i < 10; ++i) { sum += ((ULL)weight[i] * (ULL)ret[i]); } cout << sum << endl; return 0; }
#include<iostream> #include<vector> #include<string> #include<set> #include<algorithm> #include<map> using namespace std; bool cmp(pair<char, long>a, pair<char, long>b){ return a.second > b.second; } int main(){ int n; while(cin>>n){ map<char, long long>m; set<char> f; //保存首字母 for(int i=0;i<n;i++){ string s; cin>>s; long long b = 1; for(string::reverse_iterator i=s.rbegin();i<s.rend();i++){ m[*i] += b; b *= 10; } f.insert(s[0]); } vector<pair<char, long long> >v(m.begin(), m.end()); sort(v.begin(), v.end(), cmp); int i = v.size() - 1; // 所有字母出现时,找到没有出现在首字母中权重最小的字母 while(v.size()==10 && i>=0 && f.find((v[i]).first)!=f.end()){ i--; } unsigned long long res = 0; if(i!=(v.size()-1)){ // 最小字母赋值0,删除即可 v.erase(v.begin() + i); } int b = 9; for(int i=0;i<v.size();i++){ res += b * v[i].second; b--; } cout<<res<<endl; } return 0; }
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; public class DailyNews1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); String[] strs = new String[n]; for (int i = 0; i < n; i++) { strs[i] = scanner.next(); } System.out.println(maxSum(n, strs)); } } public static long maxSum(int n, String[] strs) { long sum = 0; // 返回的最大和 HashMap<Character, Long> map = new HashMap<Character, Long>(); ArrayList<Character> headList = new ArrayList<Character>(); for (int i = 0; i < n; i++) { setWeight(strs[i], map, headList); } // 按照各个字符的权重进行排序 ArrayList<Map.Entry<Character, Long>> list = new ArrayList<Map.Entry<Character, Long>>(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<Character, Long>>() { @Override public int compare(Entry<Character, Long> arg0, Entry<Character, Long> arg1) { // TODO Auto-generated method stub return arg0.getValue() > arg1.getValue() ? -1 : 1; // 根据字符的权重进行从大到小排序 } }); int number = 9;// 最大的数字 // 除去头元素为0的情况 办法:将权重最小的且不是头元素的第一个字符放置在映射值为0的位置 if (list.size() == 10) { for (int i = 9; i >= 0; i--) { if (!headList.contains(list.get(i).getKey())) {// 满足权重最小的且不是头元素的第一个字符 list.remove(i); // 去除就相当于放置在映射值为0的位置 break; } } } for (Entry<Character, Long> entry : list) { sum += entry.getValue() * number; number--; } return sum; } // 设置每个字符串中每个字符的权重,并保存首字符 public static void setWeight(String string, HashMap<Character, Long> map, ArrayList<Character> headList) { char[] cs = string.toCharArray(); long init = 1; for (int i = cs.length - 1; i >= 0; i--) { if (map.containsKey(cs[i])) { map.put(cs[i], map.get(cs[i]) + init); } else { map.put(cs[i], init); } init *= 10; } headList.add(cs[0]); } }
题意 给n(不超过50)个字符串,每个字符串(长度不超过12)由A-J的大写字符组成。要求将每个字符映射为0-9,使得每个字符串可以看作一个整数(不能有前导零),求这些字符串映射后得到数字的最大和值。(数据保证至少有一个字符不是任何字符串的首字母) 思路 根据字符所在的位置,累积统计每个字符的权值,从右到左权值分别为1, 10, 100, 1000..... 然后排序,从权值最小的到权值最大的依次映射为0-9,求和即为答案。 注意 由于每个字符串映射后得到的数字不能有前导零,因此需要记录哪些字符成为过首字母,成为过首字母的字符最终不能映射为0。所以排序后需要判断权值最小的字符是否成为过首字母,若是则需要从权值小到权值大找到第一个不为首字母的字符X,将它映射为0。在权值比X小的则依次晋级。
举例
A | B | C | D | E | F | G | H | I | J | |
---|---|---|---|---|---|---|---|---|---|---|
首字母 | F | F | T | F | T | T | F | T | T | T |
权值 | 100 | 90 | 80 | 70 | 60 | 50 | 40 | 30 | 20 | 10 |
映射 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
由于 J 成为过首字母,因此不能映射为 0
所以最终结果应为
A | B | C | D | E | F | H | I | J | G | |
---|---|---|---|---|---|---|---|---|---|---|
首字母 | F | F | T | F | T | T | T | T | T | F |
权值 | 100 | 90 | 80 | 70 | 60 | 50 | 30 | 20 | 10 | 40 |
映射 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
给字符串中的每个字符一个权重,比如:字符串 ABC ,则 A 的权重为 100 , B 的权重为 10 , C 的权重为 1 ,其实就是按照它们所在位置设定权重的。这样的话,经过多个字符串,每个字符就会得到多个权值,然后把每个字符串的权值加起来,最后按权值对每个字符从大到小排序。例如: ABC 和 BCA 两个字符串:
ABC : A=100 , B=10 , C=1
BCA : B=100 , C=10 , A=1
累加: A=100+1=101 , B=10+100=110 , C=1+10=11 ,按权值从大到小排序后得 B : 110 , A : 101 , C : 11 ,可以认为有 110 个 B ,有 101 个 A ,有 11 个 C ,那么映射 B 为 9 , A 为 8 , C 为 7 ,则最后结果为 9*110+8*101+7*11=1875.
#include <string>
#include <cstring>
#define MAX 10// 最大字母个数
using namespace std;
string input[50];// 输入字符串
long long nums[12] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000};// 权重数组
struct CountStruc{// 计数结构
char alpha;// 字母
long long count;// 权重
int num;// 映射后的数字
}countArr[MAX];
int cmp( const void *a, const void *b)// 快速排序的比较函数
{
struct CountStruc *aa = ( struct CountStruc *)a;
struct CountStruc *bb = ( struct CountStruc *)b;
return (aa->count < bb->count) ? 1 : -1;// 从大到小排序
}
int main()
{
int n;
while (cin>>n)
{
//first[] 为 hash 表,用于快速查找某个字母是否为首字母 , 因为首字母映射后不能为 0
bool first[MAX] = { false };
for ( int i=0;i<n;i++)
{
cin>>input[i];
int size = input[i].size();
for ( int j=0;j<size;j++)// 统计每个字母的权值
countArr[input[i][j]- 'A' ].alpha = input[i][j], countArr[input[i][j]- 'A' ].count += nums[size-j-1];
first[input[i][0]- 'A' ] = true ;//hash 一下
}
qsort(countArr,MAX, sizeof (countArr[0]),cmp);// 按权重排序
int zero = -1;// 标记 countArr 中哪个字母不是字符串的首字母
if (countArr[MAX-1].count>0)
{//10 个字母全部用到了
if (first[countArr[MAX-1].alpha- 'A' ])
{// 如果权值最小的字母是首字母,则需要将其向前移动
for (zero=MAX-2;zero>=0;zero--)// 找到不是首字母的字母
if (first[countArr[zero].alpha- 'A' ]== false ) break ;
countArr[zero].num = 0;// 将不是首字母的字母映射到 0
countArr[MAX-1].num = 1;// 相应地,权值最小的字母向前移一位,即映射到 1
}
}
for ( int i=0,k=MAX-1;i<MAX;i++)// 映射其他字母
if (countArr[i].count==0) break ;
else if (i!=zero) countArr[i].num = k--;
long long sum = 0;
for ( int i=0;i<MAX;i++)// 累加和
sum += countArr[i].count*countArr[i].num;
cout<<sum<<endl;
memset(countArr,0, sizeof (countArr));// 一定要清空
}
return 0;
}也来贴一个Python3的代码:
coeffs = [[0, 0] for _ in range(10)] for _ in range(int(input())): card = input() coeffs[ord(card[0]) - ord('A')][1] = 1 for i, c in enumerate(card[::-1]): coeffs[ord(c) - ord('A')][0] += 10 ** i coeffs.sort() if coeffs[0][1] == 1: for i in range(1, len(coeffs)): if coeffs[i][1] == 0: coeffs[i][0] = 0 break print(sum(i*c[0] for i, c in enumerate(sorted(coeffs))))
加和可以表示为
coeffs 为记录 A
- J
的参数、是否可在首位的二元组。第一个循环对其进行赋值后排序,这样排在首位、末位的二元组第一个元素对应 A
、J
的系数,但排在首位的二元组第二个元素可能为 1
,也就是说这个元素不能映射成 0
,需要与后续元素对调,依次向后循环找到二元组第二个元素为 0
的元素即可。
#include <iostream> #include <vector> #include <string> #include <unordered_map> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<string> vs(n); for (int i = 0; i < n; ++i) { cin >> vs[i]; } unordered_map<char, long long> cnt; unordered_map<char, bool> isHead; for (auto& s : vs) { int m = s.size(); isHead[s[0]] = 1; long long j = 1; for (int i = m - 1; i >= 0; --i) { cnt[s[i]] += j; j *= 10; } } string s = "ABCDEFGHIJ"; sort(s.begin(), s.end(), [&](char l, char r) { return cnt[l] > cnt[r]; }); if (s[9] > 0 && isHead[s[9]]) { int i; for (i = 8; i >= 0; --i) { if (!isHead[s[i]]) { break; } } string s1 = s.substr(0, i); string s2 = s.substr(i + 1, 9 - i); s2.append(1, s[i]); s = s1 + s2; } long long ans = 0; long long k = 9; for (auto c : s) { ans += k * cnt[c]; k --; } cout << ans<< endl; return 0; }
#include <iostream> #include <vector> #include <algorithm> #include <map> #include <unordered_set> using namespace std; typedef long long ll; bool cmp(pair<char, ll> a, pair<char, ll> b){ return a.second > b.second; } int main(){ int n ; cin >> n; vector<string> v; vector<pair<char, ll>> collection; unordered_set<char> head; while(n --) { string s; cin >> s; v.push_back(s); } map<char, ll> hash; for(auto &i : v) head.insert(i[0]); for(auto &x : v) { auto tmp = x ; reverse(tmp.begin(), tmp.end()); ll weight = 1; for(auto& c : tmp) { hash[c] += weight; weight *= 10; } } for(auto x : hash) collection.push_back({x.first, x.second}) ; sort(collection.begin(), collection.end(), cmp); if(hash.size() == 10) { int index = 9; while(head.count(collection[index].first)) index--; collection[index].second = 0; } sort(collection.begin(), collection.end(), cmp); ll res = 0, start = 9; for(int i = 0; i < collection.size(); i++) { res += start * collection[i].second; start--; } cout << res; }
import java.math.BigInteger; import java.util.*; /** * @author Erwei * @create 2020/7/15 at 9:38 */ public class Main{ private static class Com implements Comparator<Map.Entry<Character, Long>> { @Override public int compare(Map.Entry<Character, Long> o1, Map.Entry<Character, Long> o2) { return o1.getValue() > o2.getValue() ? 1 : -1; } } static Map<Character, Long> count; public static void main(String[] args) { Scanner in = new Scanner(System.in); try { while (in.hasNext()) { int n = in.nextInt(); in.nextLine(); ArrayList<String> ary = new ArrayList<>(); ArrayList<Character> zero = new ArrayList<>(); Map<Character, Integer> map = new HashMap<>(); count = new HashMap<>(); init(); for (int i = 0; i < n; i++) { String s = in.nextLine(); zero.add(s.charAt(0)); ary.add(s); } for (int i = 0; i < n; i++) { for (int j = 0; j < ary.get(i).length(); j++) { count.replace(ary.get(i).charAt(j), count.get(ary.get(i).charAt(j)) + (long) Math.pow(10,(double)(ary.get(i).length() - j))); } } List<Map.Entry<Character,Long>> list = new ArrayList<>(); list.addAll(count.entrySet()); Com com = new Com(); Collections.sort(list,com); Iterator<Map.Entry<Character,Long>> it = list.iterator(); for (int i = 0; it.hasNext();) { Map.Entry<Character, Long> c = it.next(); Character cha = c.getKey(); if (!zero.contains(cha)){ map.put(cha,i); list.remove(c); break; } } Iterator<Map.Entry<Character,Long>> its = list.iterator(); for (int i = 1; its.hasNext(); i++) { map.put(its.next().getKey(),i); } BigInteger sum = new BigInteger("0"); for (int i = 0; i < n; i++) { String s = ""; for (int j = 0; j < ary.get(i).length(); j++) { s += map.get(ary.get(i).charAt(j)).toString(); } BigInteger big = new BigInteger(s); sum = sum.add(big); } } }catch (Exception e){ e.printStackTrace(); } } public static void init() { count.put('A',0L); count.put('B',0L); count.put('C',0L); count.put('D',0L); count.put('E',0L); count.put('F',0L); count.put('G',0L); count.put('H',0L); count.put('I',0L); count.put('J',0L); } }
#include <iostream> #include <string> #include <vector> #include <map> #include <utility> #include <algorithm> #include <set> using namespace std; bool compare(const pair<char,long long> &p1, const pair<char, long long> &p2){ return p1.second>p2.second; } int main() { int N; cin>>N; // vector<string> vs; set<char> zero; map<char,long long> times; for(int i = 0; i < N; ++i){ string temp; cin>>temp; zero.insert(temp[0]); long long factor=1; for(int j = temp.size()-1; j >= 0; --j){ times[temp[j]]+=factor; factor*=10; } } vector<pair<char,long long>> vp(times.begin(),times.end()); sort(vp.begin(),vp.end(),compare); int index=vp.size()-1; bool pre_zero=false; for(; index >= 0; --index){ if(zero.find(vp[index].first) != zero.end()){ pre_zero=true; continue; } break; } if(pre_zero && index != -1){ auto temp=vp[index]; vp.erase(vp.begin()+index); vp.push_back(temp); } int sz=vp.size(); long long result = 0; long long cnt=9; for(int i = 0;i < sz; ++i){ long long temp = cnt*vp[i].second; result += temp; --cnt; } cout<<result; return 0; }
import java.util.*; public class Main { private void sln() { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); long sum = 0; // 两个元素分别对应 总权重、是否作过首字母 long[][] rec = new long[10][2]; for (int i = 0; i < n; i++) { String str = sc.next(); char[] chars = str.toCharArray(); // 从低位看到高位 for (int j = 1; j <= chars.length; j++) { int index = chars[chars.length - j] - 'A'; long weight = (long) Math.pow(10, j - 1); rec[index][0] += weight; if (j == chars.length) rec[index][1] = 1; } } // 按总权重排序 Arrays.sort(rec, Comparator.comparing(a -> a[0])); // 要分配的数字 0-9 int[] digits = new int[10]; for (int i = 0; i < 10; i++) digits[i] = i; // 作过首字母的话就把0和后面数字交换 for (int i = 0; i < 10; i++) { if (rec[i][1] == 1) { int temp = digits[i]; digits[i] = digits[i + 1]; digits[i + 1] = temp; } else break; } // 每个字母的总权重 乘上 对应数字 for (int i = 0; i < 10; i++) { sum += rec[i][0] * digits[i]; } System.out.println(sum); } public static void main(String[] args) { new Main().sln(); } }
参考了前面大佬的思路,才想到权重
python3.x实现
去掉注释,感觉代码量还是很少的
# 权重映射字典,记录每个字符的总权重 weight_dict = { 'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'F': 0, 'G': 0, 'H': 0, 'I': 0, 'J': 0 } # 生成9-0依次递减的数组 nums = list(range(10))[::-1] def make_weight(*args): """ 生成每个字符的权重 :param args: 输入的字符串列表 思路: 1 把字符串翻转,翻转后的下标对应权重幂数 >> ABC --> CBA >> 012 012 A的权重:10^2 B的权重:10^1 C的权重:10^0 2 分别计算每个字符串中,每个字符的权重, 用字典键的唯一性作为索引 累加每个字符的权重 """ for str_i in args: new_str = str_i[::-1] for i,letter in enumerate(new_str): weight_dict[letter] += pow(10,i) def get_max_val(): """ 利用权重计算最大值 :return: """ val = 0 # 把权重按从大到小排列 values = list(weight_dict.values()) values.sort(reverse=True) # for i, num in enumerate(values): val += num * nums[i] return val if __name__ == "__main__": # 提示用户输入 n = input("请输入行数n: ") args = [] count = 1 while int(n) >= count: args.append(input("请输入第一行字符串:").upper()) count += 1 # 生成权重获,获取最大值 make_weight(*args) result = get_max_val() print(weight_dict) print(result)
//将字符abcdefghij映射为0 ~ 9数字 让字符adcdefghij位置固定不变,变换0~9数字与之去匹配
//在首字母不能是0的情况下 最终选出累加和最大的
//生成0~9的全排列 就是字符映射成数值的所有情况
//在所有全排列中排除首字母为0的 然后去计算每种情况下的累加和 选出最大的
//超时 这种思想只能过百分之30
#include <iostream>