完全平方数>>>
> dp[i]
为数字i
的最少完全平方数,则其前一个状态dp[i-j*j]
,状态转移方程为dp[i]=Math.min(dp[i-j*j))+1
package BDyNamicProgramming;
/**
* @Author Zhou jian
* @Date 2020 ${month} 2020/4/21 0021 18:03
*/
public class Problem279 {
/**
* 给定正整数n,找到若干个完全平方数(1,4,9,16.。。。。)
* 组成和的完全平方数的个数最少
* @param n
* @return
* dp[]
*
* dp[n]为凑成n的最少的数据个数,
* 则dp[n]=1+Min(dp[n-1*1],dp[n-2*2],dp[n-3*3],dp[n-4*4],....dp[n-k*k])
* dp[1]=1
* dp[0]=0
* n必须是由给定的正整数的平方组成,
* 所以 v[13] 可能的情况为, 1 + v[12] 或 1 + v[9] 或 1 + v[4]
* 题目本质是01完全背包问题,和硬币找零钱是一样的
*
* dp[i]:表示完全平方数和为i最小的个数
*
* dp[i]为 min(dp[i],dp[i-j*j]+1)
*
*
*/
public int numSquares(int n) {
int[] dp = new int[n+1];
dp[0]=0;
dp[1]=1;
for(int i=2;i<=n;i++){
//对数组进行遍历,下标为i,每次都将当前数字先更新为最大值
//即dp[i]=i,比如i=4.最坏结果为4=1+1+1+1即为4个数字
int MinVal = i;
//状态转移方程:dp[i]=Math.min(dp[i],dp[i-j*j]),i表示当前数字,j*j表示平方数
// i-j*j表示当前数前驱一个完全平方和之后dp[i-j*J]需要求的最优解 不断分解
for(int j=1;j*j<=i;j++) MinVal=Math.min(MinVal,dp[i-j*j]);
dp[i]=MinVal+1;
}
return dp[n];
}
}