• 完全背包的变种,令dpjdpj​表示取到第ii个数的容量为jj的背包(完全平方数之和),那么dpjdpj​的最大值一定是jj本身(j∗1j∗1),那么从2≤i≤n2≤i≤n​之间做完全背包,有状态转移方程:

dpj=min⁡(dpj−i2+1,dpj)dpj​=min(dpj−i2​+1,dpj​)

#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;
}