最大价值
已知,小写字母 $a \sim z$ 的价值分别为 $w_a,w_b, \ldots, w_z$。
对于一个由小写字母构成的长度为 $l$ 的字符串 $S=s_{1} s_{2} \ldots s_{l}$,其价值为 $w_{s1} \times 1 + w_{s2} \times 2 + \ldots + w_{sl} \times l$。
现在,给定一个由小写字母构成的字符串 $S$,请你在这个字符串中插入 $k$ 个小写字母,要求最终得到的字符串的价值尽可能大。
注意:
- 插入的位置可以随意选。
- 插入的字母也可以随意选,可以插入不同字母。
输出最大可能价值。
输入格式
第一行包含一个字符串 $S$。
第二行包含一个整数 $k$。
第三行包含 $26$ 个整数 $w_a,w_b, \ldots, w_z$。
输出格式
一个整数,表示最大可能价值。
数据范围
前 $3$ 个测试点满足,$S$ 的长度范围 $[1,5]$。
所有测试点满足,$S$ 的长度范围 $[1,1000]$,$0 \leq k \leq {10}^3$,$w_a \sim w_z$ 的取值范围 $[0,1000]$。
输入样例:
abc 3 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
输出样例:
41
解题思路
来补下证明。
首先很显然每次都应该插入价值最大的字母。接下来考虑把这个字母插入到哪个位置。
假设把价值为$w_{\max}$的字母插到第$i$个位置,同时第$i+1$个位置的字母的价值为$w'$,现在交换这两个位置的字母,可以发现交换前后第$i$个位置之前的字母与第$i+1$个位置之后的字母的位置都没改变,即总价值不变,因此只用关心这两个位置的总价值就可以了。交换前的总价值为$w_{\max} \cdot i + w' \cdot (i+1)$,交换后的总价值为$w' \cdot i + w_{\max} \cdot (i+1)$。用交换前减去交换后的,$w_{\max} \cdot i + w' \cdot (i+1) - \left( w' \cdot i + w_{\max} \cdot (i+1) \right) = i \cdot (w_{\max} - w') - (i + 1) \cdot (w_{\max} - w') = - (w_{\max} - w') \leq 0$。因此交换后的价值要比交换前的价值大,所有为了取到最大价值插入的字母会一直被换到最后一个位置。
因此结论就是每次把价值最大的字母插到最后一个位置能取到最大价值。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int w[26]; 5 6 int main() { 7 string s; 8 int m; 9 cin >> s >> m; 10 int maxv = 0; 11 for (int i = 0; i < 26; i++) { 12 cin >> w[i]; 13 maxv = max(maxv, w[i]); 14 } 15 int ret = 0 16 for (int i = 0; i < s.size(); i++) { 17 ret += w[s[i] - 'a'] * (i + 1); 18 } 19 for (int i = 1; i <= m; i++) { 20 ret += maxv * (s.size() + i); 21 } 22 cout << ret; 23 24 return 0; 25 }
参考资料
AcWing 4792. 最大价值(AcWing杯 - 周赛):https://www.acwing.com/video/4591/
标签:最大,cdot,max,字母,位置,int,价值 From: https://www.cnblogs.com/onlyblues/p/17055927.html