1、题目描述
2、解题思路
要使得屏幕上显示的 A 最多,对于不同的 N ,我们可能有不同的策略。
假如 N == 3,我们肯定直接按 3 下 key1;
假如 N == 10,我们就可能在中间某个时候开始复制粘贴;
无论 N 的值如何,要使得屏幕的 A 最多,我们的操作就是下面的两种:
1、A,A,…,A,A 最后一下为 A
2、A,A,A,…CA,CC,CV,CV…,CA,CC,CV…,CV 最后一下为 CV
当 N 比较小时,CA-CC-CV 的性价比比较低,当 N 比较大时,则性价比比较高。因此,具体是哪一种得取决于 N。
分析出动态规划的状态:可以按的次数
设 dp[i] 表示在可以按 i 次按钮的情况下,屏幕最多可以显示的 A 的数量。
1、如果最后一下是 A,则 dp[i] = dp[i-1] + 1
2、如果最后一下是 CV,则得找出 CV 是从什么时候开始的。我们知道,CV 必须是在 CA CC 后才有意义,因此,我们找的就是最后一个 CA。可以是 0 到 i-2 ,即 i-2 的时候 CA,i-1 的时候 CC,然后 i 的时候 CV。
3、解题代码
class Solution {
public int maxA(int N) {
int[] dp = new int[N + 1];
dp[0] = 0; // 可以按的次数为 0,A 的数量为 0
for (int i = 1; i <= N; i++) {
dp[i] = dp[i - 1] + 1; // 最后按的是 key1,A
// 最后按的是 key4,CV
for (int j = 2; j <= i; j++) { // 遍历最后一个 CA 对应的第一个 CV 的所有可能
// 当 j == 2 时,0 处 CA,1 处 CC,2 处 CV
// dp[0] * (i-2+1) 表示对 dp[0] 时的 A 复制 (i-2+1) 次
// 当 j == i 时,i-2 处 CA,i-1 处 CC,i 处 CV
// dp[i-2] * 1 表示对 dp[i-2] 时的 A 复制 1 次
dp[i] = Math.max(dp[i], dp[j - 2] * (i - j + 1));
}
}
return dp[N];
}
}