C++ 求'的最小和;P';N个元素组成的数组中的元素不超过';k';连续的元素一起被选择

C++ 求'的最小和;P';N个元素组成的数组中的元素不超过';k';连续的元素一起被选择,c++,algorithm,dynamic-programming,C++,Algorithm,Dynamic Programming,假设数组是123445 这里N=5我们必须选择3个元素,我们不能选择超过2个连续元素,因此P=3和k=2。因此,这里的输出将是1+2+4=7 我提出了一个递归解决方案,但它的时间复杂度是指数级的。这是代码 #include<iostream> using namespace std; void mincost_hoarding (int *arr, int max_size, int P, int k, int iter, int& min_val, int sum_so

假设数组是
123445
这里
N=5
我们必须选择3个元素,我们不能选择超过2个连续元素,因此
P=3
k=2
。因此,这里的输出将是
1+2+4=7

我提出了一个递归解决方案,但它的时间复杂度是指数级的。这是代码

#include<iostream>

using namespace std;

void mincost_hoarding (int *arr, int max_size, int P, int k, int iter, int& min_val, int sum_sofar, int orig_k)
{
    if (P == 0)
    {
        if (sum_sofar < min_val)
            min_val = sum_sofar;
        return;
    }

    if (iter == max_size)
        return;



    if (k!=0)
    {
        mincost_hoarding (arr, max_size, P - 1, k - 1, iter + 1, min_val, sum_sofar + arr[iter], orig_k);
        mincost_hoarding (arr, max_size, P, orig_k, iter + 1, min_val, sum_sofar, orig_k);
    }
    else
    {
        mincost_hoarding (arr, max_size, P, orig_k, iter + 1, min_val, sum_sofar, orig_k);
    }

}



int main()
{
    int a[] = {10, 5, 13, 8, 2, 11, 6, 4};

    int N = sizeof(a)/sizeof(a[0]);
    int P = 2;
    int k = 1;


    int min_val = INT_MAX;
    mincost_hoarding (a, N, P, k, 0, min_val, 0, k);

    cout<<min_val;

}
#包括
使用名称空间std;
无效最小成本囤积(整数*arr、整数最大尺寸、整数P、整数k、整数iter、整数和最小值、整数总和、整数原点)
{
如果(P==0)
{
if(总和<最小值)
最小值=总和;
返回;
}
如果(iter==最大尺寸)
返回;
如果(k!=0)
{
最小成本囤积(arr、最大尺寸、P-1、k-1、iter+1、最小值、总和+arr[iter],原k);
最小成本囤积(arr、最大尺寸、P、原点、iter+1、最小值、总和、原点);
}
其他的
{
最小成本囤积(arr、最大尺寸、P、原点、iter+1、最小值、总和、原点);
}
}
int main()
{
INTA[]={10,5,13,8,2,11,6,4};
int N=sizeof(a)/sizeof(a[0]);
int P=2;
int k=1;
最小值=最大值;
最小成本囤积(a,N,P,k,0,最小值,0,k);

下面是一个Java动态编程算法。
(C++版本应该看起来非常类似)

其基本工作原理如下:

  • 拥有
    [pos][continued length][length]

    这里的
    length index=实际长度-1
    ),因此
    [0]
    将是长度1,类似于连续长度。之所以这样做,是因为长度0在任何地方都没有意义
  • 在每个位置:
    • 如果长度为0且连续长度为0,只需使用
      pos
      处的值即可
    • 否则,如果连续长度为0,则使用
      length-1
      查找之前所有位置(除了
      pos-1
      )中的最小值,并使用该值加上
      pos
      处的值
    • 对于其他所有内容,如果
      pos>0和连续长度>0和长度>0

      使用
      [pos-1][continued length-1][length-1]
      加上
      pos
      处的值
      如果其中一个为0,则将其初始化为无效值
一开始,我觉得这个问题只需要两个维度,然而,当我试图解决它时,我意识到我需要第三个维度

代码:

int[]arr={1,2,3,4,5};
int k=2,P=3;
int[]A=新int[arr.length][P][k];
用于(int pos=0;pos0)
{
for(int pos2=0;pos20和长度>0)
A[pos][len][con]=A[pos-1][len-1][con-1]+arr[pos];
其他的
A[pos][len][con]=1000000;
}
//确定最小和
最小整数=100000;
用于(int pos=0;pos
这里我们得到了
7
作为输出,正如预期的那样


运行时间:
O(N2k+NPk)

如果数组是{1,2,3,4,5,6}且p=4,k=3,那么可以选择1,2,4,5吗?不,那么应该选择1,2,3,5。当k=3时,最多可以同时选择3个连续元素。建议:在示例中避免使用排序数组,这是“误导性的”(对于排序数组,解决方案很简单。)原始数组排序中的连续元素?或数行中的连续元素?对于{1,5,2},P=2,k=1,答案是{1,5}或{1,2}?答案是1,2。数组排序中的连续元素。还有@Jarod42,我下次会记住这一点。选择排序的数组可能不是解释这个问题的最佳方式。+1:我认为这是一个面试问题的合适答案。我相信你也可以在一次通过数据时使用O(Pk)空格和O(NPlogk)使用[value,start position]的k length heaps的P length deque的复杂性,其中heap P存储了使用P条目的不同方法以及之前条目的不同连续编号。但是,细节有点棘手,因此我不建议在面试情况下使用它!
  int[] arr = {1, 2, 3, 4, 5};
  int k = 2, P = 3;

  int[][][] A = new int[arr.length][P][k];

  for (int pos = 0; pos < arr.length; pos++)
  for (int len = 0; len < P; len++)
  {
     int min = 1000000;
     if (len > 0)
     {
        for (int pos2 = 0; pos2 < pos-1; pos2++)
        for (int con = 0; con < k; con++)
           min = Math.min(min, A[pos2][len-1][con]);
        A[pos][len][0] = min + arr[pos];
     }
     else
        A[pos][0][0] = arr[pos];

     for (int con = 1; con < k; con++)
        if (pos > 0 && len > 0)
           A[pos][len][con] = A[pos-1][len-1][con-1] + arr[pos];
        else
           A[pos][len][con] = 1000000;
  }

  // Determine the minimum sum
  int min = 100000;
  for (int pos = 0; pos < arr.length; pos++)
  for (int con = 0; con < k; con++)
     min = Math.min(A[pos][P-1][con], min);
  System.out.println(min);