问题:给定一个正数n:得到最少的完全平方数组成的正数?
解法一:用贪心思想,每次得到最大的完全平方数,直到平方数为1.
但是这种解法没有得到最少平方数。
int tanxin(int n)
{
int t = n;
int num = 0,sum=0;
int i = (int)sqrt(t);
while (i >= 1)
{
if (sum+i*i>t)
break;
else if(sum+i*i==t)
{
cout << (i*i) ;
num++;
break;
}
else
{
cout << (i*i) << "+";
sum += i * i;
i = sqrt(t-sum);
num++;
}
}
return num;
}
思想:
易知f(1)=1;f(2)=2;f(3)=3;
当n=某一个数的平方时,易知f(n)=1;
当n=6时,f(6)的情况有2种——分别是f(1)+f(6-1)和f(4)+f(6-4),即f(1)+f(5)和f(4)+f(2)。那么f(6)的值便是这两者的最小值,即min( f(1)+f(5) , f(4)+f(2) );
情况1:f(1)的值=1,那f(5)的值等于多少呢?我们可以继续往下推:f(5)的情况有2种:f(1)+f(4)和f(4)+f(1);
情况1.1:f(1)=1,f(4)=1;那么f(5)=2;
情况1.2:f(5)=2;
最终f(5)的值为情况1.1和1.2中的最小值,即f(5)=2;
那么情况1的结构便是f(6)=3;
同理可计算出情况2的结果
…(此处省略)
解法二:递归(可得最少数)
int find_min(int n)
{
if (n <= 0)
return 0;
int min = INT_MAX;;
for (int i = 1; i <= sqrt(n); i++)
{
int t = 1 + find_min(n - i * i);
if (min > t)
min = t;
}
return min;
}
解法三:记忆递归(可得最少数)第二种的改进
int mfind_min(int n)
{
if (b[n] != -1)
return b[n];
if (n < 0)
return 0;
if (n == 0)
{
b[n] = 0;
return b[n];
}
int min = INT_MAX;;
for (int i = 1; i <= sqrt(n); i++)
{
int t= 1 + mfind_min(n - i * i);
if (min > t)
min = t;
b[n] = t;
}
return b[n];
}
解法三:dp(从下到上)
int dp(int n)
{
b[0] = 0;
for (int j = 1; j <= n; j++)
{
int min = INT_MAX;
for (int i = 1; i <= sqrt(j); i++)
{
int t = 1 + b(j - i * i);
if (min > t)
min = t;
}
b[j] = min;
}
return b[n];
}