This commit is contained in:
programmercarl
2022-11-08 09:45:36 +08:00
parent ce64a3f754
commit 730dd3c76f

View File

@ -84,16 +84,40 @@ j是从1开始遍历拆分j的情况在遍历j的过程中其实都计算
dp[i] 是依靠 dp[i - j]的状态所以遍历i一定是从前向后遍历先有dp[i - j]再有dp[i]。
枚举j的时候是从1开始的。i是从3开始这样dp[i - j]就是dp[2]正好可以通过我们初始化的数值求出来。
所以遍历顺序为:
```
```CPP
for (int i = 3; i <= n ; i++) {
for (int j = 1; j < i - 1; j++) {
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
```
注意 枚举j的时候是从1开始的。从0开始的话那么让拆分一个数拆个0的话那么求最大乘积没有意义了。
j的结束条件是 j < i - 1 其实 j < i 也是可以的不过可以节省一步例如让j = i - 1的话其实在 j = 1的时候这一步就已经拆出来了重复计算所以 j < i - 1
至于 i是从3开始这样dp[i - j]就是dp[2]正好可以通过我们初始化的数值求出来
更优化一步可以这样
```CPP
for (int i = 3; i <= n ; i++) {
for (int j = 1; j <= i / 2; j++) {
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}
```
因为拆分一个数n 使之乘积最大那么一定是拆分m个成近似相同的子数相乘才是最大的
例如 6 拆成 3 * 3 10 拆成 3 * 3 * 4 100的话 也是拆成m个近似数组的子数 相乘才是最大的
只不过我们不知道m究竟是多少而已但可以明确的是m一定大于等于2既然m大于等于也就是 最差也应该是拆成两个相同的 可能是最大值
那么 j 遍历只需要遍历到 n/2 就可以后面就没有必要遍历了一定不是最大值
至于 拆分一个数n 使之乘积最大那么一定是拆分m个成近似相同的子数相乘才是最大的 这个我就不去做数学证明了感兴趣的同学可以自己证明
5. 举例推导dp数组
@ -110,7 +134,7 @@ public:
vector<int> dp(n + 1);
dp[2] = 1;
for (int i = 3; i <= n ; i++) {
for (int j = 1; j < i - 1; j++) {
for (int j = 1; j <= i / 2; j++) {
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}