题目
分析
本题的完全平方数可以重复取,为完全背包问题。dp[i] 表示 凑成 j 的完全平方数的最少个数。递推公式就是从背包问题推出来的
dp[j] = min(dp[j],dp[j-nums[i]] + 1)
初始化,因为求最小值,为了让初始值覆盖结果,所以将初始值设为正无穷。dp[0] = 0,因为0时,完全平方数量为0。当然如果不设dp[0] = 0,直接编译会在第12行报错,超长(INT_MAX+1)且完全背包问题,正序遍历背包。
代码
1 class Solution { 2 public: 3 int numSquares(int n) { 4 vector<int>nums; //存放完全平方数 5 for(int i = 1;i * i <= n;i++){ 6 nums.push_back(i*i); 7 } 8 vector<int>dp(n+1,INT_MAX); 9 dp[0] = 0; 10 for(int i = 1;i < nums.size();i++){ 11 for(int j = nums[i];j <= n;j++){ 12 dp[j] = min(dp[j],dp[j-nums[i]] + 1); 13 } 14 } 15 return dp[n]; 16 } 17 };
优化后
1 class Solution { 2 public: 3 int numSquares(int n) { 4 vector<int>dp(n+1,INT_MAX); 5 dp[0] = 0; 6 //先遍历物品再遍历背包,可以交换遍历顺序 7 for(int i = 1;i * i <= n;i++){ 8 for(int j = i*i;j <= n;j++){ 9 dp[j] = min(dp[j],dp[j-i*i] + 1); 10 } 11 } 12 return dp[n]; 13 } 14 };