【动态规划初识】整数划分
每日一道算法题之整数划分
- 一、题目描述
- 二、思路
- 三、C++代码
一、题目描述
题目来源:LeetCode
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
C++程序要求输入输出格式如下:
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
二、思路
根据DP解题步骤:
1.确定dp数组(dp table)以及下标的含义
dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。
2.确定递推公式
其实可以从1遍历j,然后有两种渠道得到dp[i].
一个是j * (i - j) 直接相乘。
一个是j * dp[i - j],相当于是拆分(i - j)。
那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
3.dp的初始化
这里只初始化dp[2] = 1,从dp[i]的定义来说,拆分数字2,得到的最大乘积是1,这个没有任何异议!
4.确定遍历顺序
确定遍历顺序,先来看看递归公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]。
5.举例推导dp数组
dp[2]=1,dp[3]=2,dp[4]=4,dp[5]=6
dp[6]=9,dp[7]=12,dp[8]=18,dp[9]=27
dp[10]=36
三、C++代码
#include<bits/stdc++.h>
using namespace std;//整数拆分 #define maxsize 1000
int dp[maxsize];int main(){int n;cin>>n;dp[2]=1;//dp数组初始化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)); //状态转移方程 }} cout<<dp[n];
}