Algorithm 动态规划交替算法
我正试图构建一个在O(nb)时间运行的算法,使用以下输入/问题: 输入:一个由n个不同整数和一个整数b组成的数组A[1..n](我假设A中的数字是连续的,从1开始到n结束,即n=4 A[1,2,3,4])。 问:当A[]中的元素只能使用一次时,b可以通过多少种方式写入数组中的元素之和Algorithm 动态规划交替算法,algorithm,dynamic,dynamic-programming,Algorithm,Dynamic,Dynamic Programming,我正试图构建一个在O(nb)时间运行的算法,使用以下输入/问题: 输入:一个由n个不同整数和一个整数b组成的数组A[1..n](我假设A中的数字是连续的,从1开始到n结束,即n=4 A[1,2,3,4])。 问:当A[]中的元素只能使用一次时,b可以通过多少种方式写入数组中的元素之和 我在这个问题上遇到了麻烦。我在寻找某种递归解决方案,但我不知道如何避免使用重复数。例如,如果我们从1开始,存储所有的方法,使1(仅1)然后2(仅2)然后3(3或2+1)等等,我们不难看出有多少方法可以得到更大的数字
我在这个问题上遇到了麻烦。我在寻找某种递归解决方案,但我不知道如何避免使用重复数。例如,如果我们从1开始,存储所有的方法,使1(仅1)然后2(仅2)然后3(3或2+1)等等,我们不难看出有多少方法可以得到更大的数字。但是,例如,如果我们取5,我们将看到它可以被分解为4+1,4可以进一步分解为3+1,那么我们将看到2个解决方案(4+1和3+1+1),但其中一个有一个数字的重复。我遗漏了什么明显的东西吗?非常感谢!但这不是一个动态编程解决方案。非递归。
假设arr在您的例子中被排序,如[i..j],其中[i]在C中的递归和动态解:
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef struct tAddend
{
struct tAddend* pPrev;
uint Value;
} tAddend;
void findRecursiveSolution(uint n, uint maxAddend, tAddend* pPrevAddend)
{
uint i;
for (i = maxAddend; ; i--)
{
if (n == 0)
{
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
return;
}
if (n >= i && i > 0)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = i;
findRecursiveSolution(n - i, i - 1, &a);
}
if (i <= 1)
{
break;
}
}
}
void printDynamicSolution(uchar** pTable, uint n, uint idx, uint sum, tAddend* pPrevAddend)
{
uchar el = pTable[idx][sum];
assert((el != 0) && (el != 5) && (el != 7));
if (el & 2) // 2,3,6 - other(s)
{
printDynamicSolution(pTable,
n,
idx - 1,
sum,
pPrevAddend);
}
if (el & 4) // self + other(s)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
printDynamicSolution(pTable,
n,
idx - 1,
sum - (idx + 1),
&a);
}
if (el & 1) // self, found a solution
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
pPrevAddend = &a;
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
}
}
void findDynamicSolution(uint n)
{
uchar** table;
uint i, j;
if (n == 0)
{
return;
}
// Allocate the DP table
table = malloc(sizeof(uchar*) * n);
if (table == NULL)
{
printf("not enough memory\n");
return;
}
for (i = 0; i < n; i++)
{
table[i] = malloc(n + 1);
if (table[i] == NULL)
{
while (i > 0)
{
free(table[--i]);
}
free(table);
printf("not enough memory\n");
return;
}
}
// Fill in the DP table
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0)
{
table[i][j] = (i + 1 == j); // self
}
else
{
table[i][j] = (i + 1 == j) + // self
2 * (table[i - 1][j] != 0) + // other(s)
4 * ((j >= i + 1) && (table[i - 1][j - (i + 1)] != 0)); // self + other(s)
}
}
}
printDynamicSolution(table, n, n - 1, n, NULL);
for (i = 0; i < n; i++)
{
free(table[i]);
}
free(table);
}
int main(int argc, char** argv)
{
uint n;
if (argc != 2 || sscanf(argv[1], "%u", &n) != 1)
{
n = 10;
}
printf("Recursive Solution:\n");
findRecursiveSolution(n, n, NULL);
printf("\nDynamic Solution:\n");
findDynamicSolution(n);
return 0;
}
另请参见。设F(x,i)为[1:i]元素求和得到x的方法数
F(x,i+1) = F(x-A[i+1],i) + F(x,i)
就是这样!我可能遗漏了一些东西,但看起来这个解决方案只能给出由2个数字组成的答案,即对于6,它找不到3+2+1?是的,你是对的。我从你的帖子中猜错了。抱歉。是的,你肯定可以使用动态编程来解决这个问题。对于这个问题,肯定需要使用2D数组不,我将编辑回复。谢谢,这正是我想要的!(感谢所有提供解决方案的人,他们也提供了帮助!:)
Recursive Solution:
+10
+1+9
+2+8
+3+7
+1+2+7
+4+6
+1+3+6
+1+4+5
+2+3+5
+1+2+3+4
Dynamic Solution:
+1+2+3+4
+2+3+5
+1+4+5
+1+3+6
+4+6
+1+2+7
+3+7
+2+8
+1+9
+10
F(x,i+1) = F(x-A[i+1],i) + F(x,i)