解题思路:

  • 完全背包的变种,令dpjdp_j表示取到第ii个数的容量为jj的背包(完全平方数之和),那么dpjdp_j的最大值一定是jj本身(j1j*1),那么从2in2 \leq i \leq \sqrt{n}之间做完全背包,有状态转移方程:
dpj=min(dpji2+1,dpj)dp_j = \min(dp_{j-i^2}+1,dp_j)
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<int> dp(n+1);
    for(int i = 1; i <= n; ++i){
        dp[i] = i;
    }
    for(int i = 2; i <= (int)sqrt(n); ++i){
        for(int j = 0; j <= n-i*i; ++j){
            dp[j+i*i] = min(dp[j+i*i],dp[j]+1);
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}