Array
A ={1,2,3}
对于Sum值= 5
可能的组合
{3,2} , {1,1,1,1,1} , {2,2,1} and all possiable one
这是我的方法:
int count( int S[], int m, int n )
{
// m is the size of the array and n is required sum
// If n is 0 then there is 1 solution (do not include any coin)
if (n == 0)
return 1;
// If n is less than 0 then no solution exists
if (n < 0)
return 0;
// If there are no coins and n is greater than 0, then no solution exist
if (m <=0 && n >= 1)
return 0;
// count is sum of solutions (i) including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
我的方法缺点::必须一次又一次地重新计算多种组合。因此,sum的值非常高,所以它很慢。
我想用动态编程实现这个请给我一个解释如何存储计算值以便我可以重用它减少了我的计划时间
答案 0 :(得分:2)
我会采用不同的方式:
生成硬币数组以匹配总和
<=
,然后是目标总和计算排列/组合,如果订单也很重要
示例(适用于1.):
coins = { 5,2,1 }
sum=7
5 | 2
5 | - | 1 1
- | 2 2 2 | 1
- | 2 2 | 1 1 1
- | 2 | 1 1 1 1 1
|
分隔递归图层[edit1] C ++源代码
//---------------------------------------------------------------------------
void prn_coins(int *count,int *value,int coins) // just to output solution somewhere
{
int i;
AnsiString s="";
for (i=0;i<coins;i++)
s+=AnsiString().sprintf("%ix%i ",count[i],value[i]);
Form1->mm_log->Lines->Add(s);
}
//---------------------------------------------------------------------------
void get_coins(int *count,int *value,int coins,int sum,int ix=0,int si=0)
{
if (ix>=coins) return; // exit
if (ix==0) // init:
{
ix=0; // first layer
si=0; // no sum in solution for now
for (int i=0;i<coins;i++) count[i]=0; // no coins in solution for now
}
//1. genere actal coint type value[]
count[ix]=(sum-si)/value[ix]; // as close to sum as can
si+=value[ix]*count[ix]; // update actual sum
for(;;)
{
//2. recursion call
if (si==sum) prn_coins(count,value,coins);
else get_coins(count,value,coins,sum,ix+1,si);
//3. next combination
if (count[ix]) { count[ix]--; si-=value[ix]; }
else break;
}
}
//---------------------------------------------------------------------------
void main()
{
const int _coins=3; // coin types
int value[_coins]={5,2,1}; // coin values (must be in descending order !!!)
int count[_coins]={0,0,0}; // coin count in actual solution (RLE)
get_coins(count,value,_coins,7);
}
//-------------------------------------------------------------------------
答案 1 :(得分:2)
对您的解决方案进行一个非常简单的更改就是添加&#34; memoization&#34;。
考虑到数组S
修复了函数的结果,只取决于m
和n
。因此,您可以进行以下小改动:
int count( int S[], int m, int n ) {
...
if (cache[m][n] == -1) {
cache[m][n] = count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
return cache[m][n];
}
这样,您只需为每对不同的值m
和n
计算一次结果。
我们的想法是将(m
,n
)索引的二维数组全部初始化为-1
(意思是&#34;尚未计算&#34;)。当您要计算count
中的值时,首先检查该值是否尚未计算,如果是这种情况,您还将结果存储在2d矩阵中,这样您就不会重新计算在将来再次出现。
答案 2 :(得分:0)
对于动态编程,您需要概括您的问题。让S(a, x)
成为所有可能的值x
的总和,仅使用从A
开始的a
值。您的原始问题是S(0, X)
。
由于你有一个带有两个参数的离散函数,你可以将它的结果存储在一个二维数组中。
有一些简单的案例:a = A.length
和X > 0
没有解决方案。
该集只包含X = 0
的空值。
现在,您应该找到其他情况的递归公式,并以这样的方式填充表格,即您已经计算了您所依赖的索引(提示:考虑向后循环)。