打印解决方案以获取数组中非连续元素的最大和

时间:2019-05-19 06:21:22

标签: c++ arrays dynamic-programming

我正在尝试显示一个数组中的元素,这些元素的总和为最大,并且没有两个元素是连续的(相邻的)。

我想出了如何通过保持数组元素的 inclusive exclusive 之和来计算最大总和的方法。是否有优化的方法来捕获构成最大和的所有元素并以相反的顺序显示

代码:

int i_sum = tickets[0];
int e_sum = 0;
int new_sum = 0
int sum = 0;
for (int i = 1; i < n; i++)
{
   new_sum = (i_sum > e_sum) ? i_sum : e_sum;
   i_sum = e_sum + tickets[i];
   e_sum = new_sum;
 }
 (i_sum >= e_sum) ? std::cout << "incl " << i_sum : std::cout << "excl " << e_sum;

例如:

n = 8

array = [100,-3,200,50,400,-7,20,80]

最大总和= 780

输出: 80,400,200,100

如果包含和与排除的总和相同,则输出将是具有更大元素集的输出。

案例:

n = 4

array = [4,5,4,3]

最大总和= 8

输出:4、4

我应该维护两个不同的数组来保存所有可能的值,还是在每次通过时一次将它们插入一个?

谢谢。

1 个答案:

答案 0 :(得分:1)

是的,您可以维护两个数组,并在每个步骤进行复制和交换。但是,这不是最佳的。它将使您的算法 O(n 2

  std::vector<int> incl, excl;
  if (tickets[0] > 0)
    incl.push_back(tickets[0]);

  for (int i = 1; i < n; i++)
  {
    std::vector<int> temp;
    if (i_sum > e_sum) {
      new_sum = i_sum;
    } else {
      new_sum = e_sum;
      temp = excl;
   }
   i_sum = e_sum + tickets[i];
   e_sum = new_sum;
   excl.push_back(tickets[i]);
   std::swap(incl, excl);
   if (temp.size())
     excl = temp;
  }

inclexcl将包含您的解决方案,以较大者为准。

我使用std::swap进行了一个小的优化,以使用避免复制的移动语义,但是当使用e_sum > i_sum时,我们无法避免将temp复制到excl

相反,可以使用动态编程来表达相同的问题,您可以在 O(n)中完成此任务。这个想法是相似的。要么包含当前元素,然后将其添加到解决方案中,以使第二个先前元素的总和最大,要么排除当前元素以获取先前元素的解决方案。代码如下:

  vector <int> dp(n);
  vector <int> parent(n, 0);
  if (tickets[0] > 0) {
    dp[0] = tickets[0];
    parent[0] = tickets[0];
  }
  if (tickets[1] > 0) {
    dp[1] = tickets[1];
    parent[1] = tickets[1];
  }
  for (int i = 2; i < n ; i++) {
    if (dp[i-1] > tickets[i] + dp[i-2]) {
      dp[i] = dp[i-1];
    } else {
      dp[i] = tickets[i] + dp[i-2];
      parent[i] = tickets[i];
    }
  }
  cout << "Max sum: " << dp[n-1] << endl;

  for(int i = n - 1; i >= 0;) {
    if (parent[i]) {
      cout << parent[i] << ' ';
      i = i - 2;
    } else {
      i--;
    }
  }

parent向量可用于追溯动态编程解决方案所采取的步骤。

请注意,问题中提到的解决方案略有错误。如果第一个元素为负,则会得到不理想的结果。