今日头条2017后端工程师实习生笔试题

 第一题:

传送门

[编程题]最大映射

有 n 个字符串,每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字。这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零。现在问你怎样映射字符才能使得这些字符串表示的整数之和最大?


输入描述:

每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串。 n 不大于 50,且至少存在一个字符不是任何字符串的首字母。



输出描述:

输出一个数,表示最大和是多少。


输入例子:
2
ABC
BCA

输出例子:
1875

题解转自:

http://blog.csdn.net/yang20141109/article/details/51284495

解析:给大写字母A~J中的每一个字母赋一个权重,按照权重由大到小进行排序,依次把9~0十个数字赋值给排序好的的字母。问题的关键就在于我们如何给字母赋值权重。假如我们有字符串"ABCD",我们从低位到高位依次给每个字母赋值为1,10,100,1000...等。w(D) = 1,w(C) = 10,w(B) = 100,w(A) = 1000。最后我们把输入字符串中的每个字符的权重相加。比如字符串"ABC"和字符串"BCA"。赋值及求和如下图所示:

    因为字符串映射为的整数不存在前导零,所以我们需要做一步特殊的处理,在每个字符串首位置出现的字符都不能为零。如果出现这种情况,我们需要把不在首部出现的具有最小权值字符提到排好序的数组的首部。
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5  
 6 using namespace std;
 7  
 8 #define N 55
 9 #define M 30
10 #define ll long long
11  
12 char s[N][M];
13 int flag[M];
14 int le[N];
15 int n;
16 ll ma;
17 
18 struct PP{
19     ll quan;
20     ll ch;
21 }X[N],te;
22 
23 bool cmp(PP a,PP b){
24     return a.quan < b.quan;
25 }
26  
27 void ini(){
28     int i,j;
29     memset(flag,0,sizeof(flag));
30     memset(X,0,sizeof(X));
31     ma = 0;
32     for(i = 0;i < n;i++){
33         scanf("%s",s[i]);
34         le[i] = strlen(s[i]);
35     }
36     ll temp = 1;
37     for(i = 0;i < n;i++){
38         flag[ s[i][0] - 'A' ] = -1;
39         temp = 1;
40         for(j = le[i] - 1;j >= 0;j--){
41             X[ s[i][j] - 'A' ].quan += temp;
42             X[ s[i][j] - 'A' ].ch = s[i][j] - 'A';
43             temp *= 10;
44         }
45     }
46 }
47 
48 void solve(){
49     sort(X,X + 10,cmp);
50     int i;
51     int pos;
52     if(X[0].quan != 0){
53         for(i = 0;i < 10;i++){
54             if(flag[ X[i].ch ] == -1){
55                 continue;
56             }
57             else{
58                 pos = i;
59                 te = X[i];
60                 break;
61             }
62         }
63         for(i = pos - 1;i >= 0;i--){
64             X[i+1] = X[i];
65         }
66         X[0] = te;
67     } 
68     for(i = 0;i < 10;i++){
69         ma += i * X[i].quan;
70     }
71     
72 }
73  
74 int main(){
75     while(scanf("%d",&n) != EOF){
76         ini();
77         solve();
78         printf("%lld
",ma);
79     }
80 }

第二题:

[编程题] 木棒拼图

有一个由很多木棒构成的集合,每个木棒有对应的长度,请问能否用集合中的这些木棒以某个顺序首尾相连构成一个面积大于 0 的简单多边形且所有木棒都要用上,简单多边形即不会自交的多边形。

初始集合是空的,有两种操作,要么给集合添加一个长度为 L 的木棒,要么删去集合中已经有的某个木棒。每次操作结束后你都需要告知是否能用集合中的这些木棒构成一个简单多边形。


输入描述:

每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n 表示操作的数量(1 ≤ n ≤ 50000) , 接下来有n行,每行第一个整数为操作类型 i (i ∈ {1,2}),第二个整数为一个长度 L(1 ≤ L ≤ 1,000,000,000)。如果 i=1 代表在集合内插入一个长度为 L 的木棒,如果 i=2 代表删去在集合内的一根长度为 L 的木棒。输入数据保证删除时集合中必定存在长度为 L 的木棒,且任意操作后集合都是非空的。



输出描述:

对于每一次操作结束有一次输出,如果集合内的木棒可以构成简单多边形,输出 "Yes" ,否则输出 "No"。


输入例子:
5
1 1
1 1
1 1
2 1
1 2

输出例子:
No
No
Yes
No
No

注意:

multiset<ll>s;

用multiset删除某个数要用:

s.erase(s.find(y));

s.erase(y);

会把相同的数一起删除

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<set>
 6 
 7 using namespace std;
 8 
 9 #define N 50005
10 #define ll long long
11 
12 ll sum;
13 ll ma;
14 int n;
15 int sz;
16 
17 int main(){
18     while(scanf("%d",&n) != EOF){
19         ma = 0;
20         sum = 0;
21         multiset<ll>s;
22         multiset<ll>::iterator it;
23         int i;
24         int x;
25         ll y;
26         for(i = 0;i < n;i++){
27             scanf("%d%lld",&x,&y);
28             if(x == 1){
29                 s.insert(y);
30                 sum += y;
31             }
32             else{
33                 s.erase(s.find(y));
34                 sum -= y;
35             }
36             it = s.end();
37             it --;
38             ma = *it;
39             sz = s.size();
40             if(sz >= 3 && (sum - ma) > ma ){
41                 printf("Yes
");
42             }
43             else{
44                 printf("No
");
45             }
46         }
47     }
48     
49 }
原文地址:https://www.cnblogs.com/njczy2010/p/5615937.html