Algorithm 动态规划交替算法

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)等等,我们不难看出有多少方法可以得到更大的数字

我正试图构建一个在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)等等,我们不难看出有多少方法可以得到更大的数字。但是,例如,如果我们取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)