动态规划问题:用c++实现将一个整数分解成若干个整数的和,且这些整数都是2的k次方(k>=0)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划问题:用c++实现将一个整数分解成若干个整数的和,且这些整数都是2的k次方(k>=0)相关的知识,希望对你有一定的参考价值。

动态规划问题:用c++实现将一个整数分解成若干个整数的和,且这些整数都是2的k次方(k>=0),问:有多少种解法?
比如
5=1+1+1+1+1
5=1+1+1+2
5=1+2+2
5=1+4
有四种分解方法
另附我的代码:
#include<iostream>
using namespace std;
int Array[21]=1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576;
_int64 Record[1000001][21]=0;
int partition(int n,int k)//n不超过2^k的分解

if(Record[n][k]!=0)

return Record[n][k];

else

if(n==1||k==0)

Record[n][k]=1;
return Record[n][k];

else if(n<Array[k])


Record[n][k]=partition(n,k-1)%1000000000;
return Record[n][k];

else

Record[n][k]=(partition(n,k-1)+partition(n-Array[k],k))%1000000000;
return Record[n][k];




int main()

int n=1,k=0;
while(n)

k=0;
cout<<"n:";
cin>>n;
if(n>0)

while(n>Array[k]&&k<21)

k++;

cout<<partition(n,k-1)%1000000000<<endl;


return 0;


当n大于100000时就出错,n较小时能正常运行,请帮帮忙,修改代码或者给出你的答案都可以
n<=1000000,所以为了输出的数值小一点,故对1000000000求模

一楼说的不错,不过没有解决我的问题,当输入n=100000,k是不会大于20的

动态规划转移方程:

a[n] = a[n-1] ,n是奇数
a[n] = a[n-2] + a[n/2] ,n 是偶数

代码:

#include<iostream>
using namespace std;
__int64 a[1000100];
int flag(0);
int main()

a[0] = 1;
a[1] = 1;
a[2] = 2;
while(cin>>n,n) //input integer n

for(int i=flag;i<=n;++i)

if(i&1) a[i]=a[i-1]%1000000000;
else a[i] = (a[i-2]+a[i>>1])%1000000000;

flag = n;
cout<<a[n]<<endl;

return 0;


方程的想法有一点难以理解,其实你仔细想想也是可以理解的,需要细细琢磨
参考技术A while(n>Array[k]&&k<21)

k++;


这个循环中,当n=100000时,进入循环到k=20时,下一次k=21
但是计算n>Array[k]即n>Array[21]访问数组越界了,要计算更大的数只能增加数组Array元素个数。

另外要避免这种情况可以把while(n>Array[k]&&k<21)改成while(k<21&&n>Array[k])
参考技术B 实际算法变成

一个整数 用二进制表示 是由若干位为1的位组成

获取各二进制位为1的位置号 然后组合

动态规划

四、基本思想:动态规划思想通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。但是适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。

 

五、解题思路:

1.找出最优解的性质,刻画其结构特征和最优子结构特征;
2.递归地定义最优值,刻画原问题解与子问题解间的关系,找到状态方程;
3.以自底向上的方式计算出各个子问题最优解,并避免子问题的重复计算;
4.根据计算最优值时得到的信息,构造最优解。
---------------------
作者:锐小6
来源:CSDN
原文:https://blog.csdn.net/qq_39630587/article/details/79134217
版权声明:本文为博主原创文章,转载请附上博文链接!

 

动态规划

通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

基本思想

若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

分治与动态规划

共同点:二者都要求原问题具有最优子结构性质,都是将原问题分而治之,分解成若干个规模较小(小到很容易解决的程序)的子问题.然后将子问题的解合并,形成原问题的解.

不同点:分治法将分解后的子问题看成相互独立的,通过用递归来做。

     动态规划将分解后的子问题理解为相互间有联系,有重叠部分,需要记忆,通常用迭代来做。

问题特征

最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。

重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。

步骤

描述最优解的结构

递归定义最优解的值

按自底向上的方式计算最优解的值

由计算出的结果构造一个最优解

注意需要需要二维数组用容器,C++动态分配二维数组太坑爹

典型问题

01背包问题

背包九讲:http://www.cnblogs.com/jbelial/articles/2116074.html

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 

f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}。

 

http://www.cnblogs.com/raichen/p/5772056.html









以上是关于动态规划问题:用c++实现将一个整数分解成若干个整数的和,且这些整数都是2的k次方(k>=0)的主要内容,如果未能解决你的问题,请参考以下文章

树形动态规划

动态规划理论

c++ 分解数2

动态规划

动态规划

五种常用算法之二:动态规划算法