1. 题目背景与核心挑战
UVa 12261 "High Score"是ICPC竞赛中的一道经典动态规划题目,题目要求玩家在给定的数字序列中,通过插入加号或乘号来构造表达式,使得最终计算结果最大化。这道题看似简单,实则暗藏多个需要深入思考的算法陷阱。
我第一次遇到这个问题是在2017年亚洲区域赛的线上训练赛中。当时我们团队花了近40分钟才完全理解题目要求并找到正确解法。这道题最精妙之处在于它打破了我们对运算符优先级的常规认知——题目明确说明所有运算符具有相同的优先级,都从左到右计算。这意味着表达式"1+2*3"将被计算为(1+2)3=9,而非常规的1+(23)=7。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与解法思路
2.1 输入输出规范解析
题目输入由T个测试用例组成,每个用例给出一个数字字符串S(1≤|S|≤50)。输出需要对每个字符串给出通过插入运算符后能得到的最大数值。例如:
code复制输入:123
输出:15(因为1+2*3=15)
关键约束条件:
- 必须在每两个相邻数字间插入+或*
- 所有运算符优先级相同,从左到右计算
- 数字没有前导零(输入保证合法)
2.2 动态规划状态设计
这道题的标准解法是使用动态规划。我们需要定义dp[i][j]表示子串S[i..j]能获得的最大值。状态转移方程为:
dp[i][j] = max{
dp[i][k] + dp[k+1][j],
dp[i][k] * dp[k+1][j]
} 对于所有i≤k<j
初始条件是dp[i][i] = S[i] - '0'(单个数字的值)
2.3 算法优化技巧
直接实现上述DP会有O(n^3)时间复杂度,对于n=50来说完全可接受。但在竞赛中还可以进一步优化:
- 预处理数字值:预先计算所有子串的数值,避免重复转换
- 记忆化搜索实现:可能比迭代式DP更易编写且不易出错
- 边界条件处理:特别注意单个数字和两个数字的情况
3. 关键实现细节与代码解析
3.1 预处理数字值的技巧
cpp复制int num[55][55]; // num[i][j]表示子串S[i..j]的数值
for(int i=0; i<n; i++) {
int val = 0;
for(int j=i
