首先我们了解一下贪心算法
举例 :一根绳子 长度为8 怎么剪 每段绳子的乘积最大?
这里我们找规律 只有剪成n个长度为三的绳子 乘积最大 但是 这样剪会遇到以下几种情况
1.剩了一段长度为1的绳子
如果遇到这种情况 我们就少剪出一段长度为3的绳子 用这一段和剩下的长度为1的绳子拼一下 得到长度为4 的绳子 再将它剪成2段长度为2 的绳子
2.剩了一段长度为2的绳子
假设减了n个长度为3的绳子 剩了一段长度为2的绳子
乘积=3*n*2;
3.没剩
乘积=3*n;
具体代码如下
int cNum(int Num)
{
//排除小于等于3的情况
if (Num < 2)
return 0;
if (Num == 2)
return 2;
if (Num == 3)
return 3;
//绳子大于3 nCountof3记录段数
int nCountof3 = Num / 3;
if (Num - nCountof3 == 1)//余下的绳子长度=1 少剪一段长度为3的 用于和长度为1的拼
nCountof3--;
//判断剩了的绳子可以剪成几段长度为2的绳子
int nCountof2 =(Num - nCountof3 *3)/ 2;
return (int)pow(3, nCountof3) *(int)pow(2, nCountof2);//乘积=3的(nCountof3)次方*2的(nCountof2)次方
}
接下来 了解一下动态规划
动态分配一般当前的问题会与之前处理的两个问题有关联
如:
斐波那契数列 f(n)=f(n-1)+f(n-2);
一般我们采用动态分配的方法时 都会生成这样一种解决方案的函数
在这道题中 我们的思路是
开辟一个数组
当前元素等于 下标相加等于当前元素的下标 的两个元素的乘积的最大值
如当前元素为4 1,3 2,2 符合 那么看 pArr[1]*pArr[3] 和 pArr[2]*pArr[2] 谁大 大的乘积为pArr[4]的值
代码如下
int DP(int Num)
{
if (Num < 2)
return 0;
if (Num == 2)
return 2;
if (Num == 3)
return 3;
int* pArr = new int[Num + 1];
::memset(pArr, 0, sizeof(int) * (Num + 1));
pArr[0] = 0;
pArr[1] = 1;
pArr[2] = 2;
pArr[3] = 3;
int Sum = 0;
for (int i = 4; i <= Num; i++)
{
int max = 0;
for (int j = 0; j < i / 2; j++)
{
if (pArr[j+1] * pArr[i - j - 1] > max)
{
max=pArr[j+1] * pArr[i - j - 1];
}
}
pArr[i] = max;
Sum = max;
}
delete []pArr;
pArr = NULL;
return Sum;
}