📜  具有最小和的大小为 k 的非递减子序列

📅  最后修改于: 2021-09-17 07:46:52             🧑  作者: Mango

给定一个由 n 个整数组成的序列,你必须找出长度为 k 且总和最小的非递减子序列。如果不存在序列,则输出 -1。
例子 :

Input : [58 12 11 12 82 30 20 77 16 86], 
        k = 3
Output : 39
{11 + 12 + 16}

Input : [58 12 11 12 82 30 20 77 16 86], 
        k = 4
Output : 120
{11 + 12 + 20 + 77}

Input : [58 12 11 12 82 30 20 77 16 86], 
        k = 5
Output : 206

令solve(i, k) 是在索引i 处结束的大小为k 的子序列的最小和。那么就会有两种状态:
1. 包括当前元素。 {求解(j, k-1) + a[i]}
2. 排除当前元素。 {解决(j,k)}
我们的重复状态是:

dp[i][k] = min(solve(j, k-1) + a[i], solve(j, k)) 
  if a[i] >= a[j] for all 0 <= j <= i.
C++
// C++ program to find Non-decreasing sequence
// of size k with minimum sum
#include 
using namespace std;
const int MAX = 100;
const int inf = 2e9;
 
// Global table used for memoization
int dp[MAX][MAX];
 
void initialize()
{
    for (int i = 0; i < MAX; i++)
        for (int j = 0; j < MAX; j++)
            dp[i][j] = -1;
}
 
int solve(int arr[], int i, int k)
{
    // If already computed
    if (dp[i][k] != -1)
        return dp[i][k];
 
    // Corner cases
    if (i < 0)
        return inf;
    if (k == 1) {
        int ans = inf;
        for (int j = 0; j <= i; j++)
            ans = min(ans, arr[j]);
        return ans;
    }
 
    // Recursive computation.
    int ans = inf;
    for (int j = 0; j < i; j++)
        if (arr[i] >= arr[j])
            ans = min(ans, min(solve(arr, j, k),
                               solve(arr, j, k - 1) + arr[i]));
        else {
            ans = min(ans, solve(arr, j, k));
        }
 
    dp[i][k] = ans;
    return dp[i][k];
}
 
// Driver code
int main()
{
    initialize();
    int a[] = { 58, 12, 11, 12, 82, 30,
                20, 77, 16, 86 };
    int n = sizeof(a) / sizeof(a[0]);
    int k = 4;
    cout << solve(a, n - 1, k) << endl;
    return 0;
}


Java
// Java program to find Non-decreasing sequence
// of size k with minimum sum
import java.io.*;
import java.util.*;
 
class GFG {
    public static int MAX = 100;
    public static int inf = 1000000;
 
    // Table used for memoization
    public static int[][] dp = new int[MAX][MAX];
 
    // initialize
    static void initialize()
    {
        for (int i = 0; i < MAX; i++)
            for (int j = 0; j < MAX; j++)
                dp[i][j] = -1;
    }
 
    // Function to find non-decreasing sequence
    // of size k with minimum sum
    static int solve(int arr[], int i, int k)
    {
        // If already computed
        if (dp[i][k] != -1)
            return dp[i][k];
 
        // Corner cases
        if (i < 0)
            return inf;
        if (k == 1) {
            int ans = inf;
            for (int j = 0; j <= i; j++)
                ans = Math.min(ans, arr[j]);
            return ans;
        }
 
        // Recursive computation
        int ans = inf;
        for (int j = 0; j < i; j++)
            if (arr[i] >= arr[j])
                ans = Math.min(ans, Math.min(solve(arr, j, k), solve(arr, j, k - 1) + arr[i]));
            else
                ans = Math.min(ans, solve(arr, j, k));
 
        dp[i][k] = ans;
 
        return dp[i][k];
    }
 
    // driver program
    public static void main(String[] args)
    {
        initialize();
        int a[] = { 58, 12, 11, 12, 82, 30,
                    20, 77, 16, 86 };
        int n = a.length;
        int k = 4;
        System.out.println(solve(a, n - 1, k));
    }
}
 
// Contributed by Pramod Kumar


Python
# Python program to find Non-decreasing sequence
# of size k with minimum sum
  
# Global table used for memoization
dp = []
for i in xrange(10**2 + 1):
    temp = [-1]*(10**2 + 1)
    dp.append(temp)
  
def solve(a, i, k):
    if dp[i][k] != -1:  # Memoization
        return dp[i][k]
    elif i < 0: # out of bounds
        return float('inf')
  
    # when there is only one element
    elif k == 1:   
        return min(a[: i + 1])
  
    # Else two cases
    # 1 include current element
    # solve(a, j, k-1) + a[i]
    # 2 ignore current element
    # solve(a, j, k)
    else: 
        ans = float('inf')
        for j in xrange(i):
            if a[i] >= a[j]:
                ans = min(ans, solve(a, j, k), solve(a, j, k-1) + a[i])
            else:
                ans = min(ans, solve(a, j, k))
        dp[i][k] = ans
        return dp[i][k]
  
# Driver code
a = [58, 12, 11, 12, 82, 30, 20, 77, 16, 86]       
print solve(a, len(a)-1, 4)


C#
// C# program to find Non-decreasing sequence
// of size k with minimum sum
using System;
 
class GFG {
     
    public static int MAX = 100;
    public static int inf = 1000000;
 
    // Table used for memoization
    public static int[, ] dp = new int[MAX, MAX];
 
    // initialize
    static void initialize()
    {
        for (int i = 0; i < MAX; i++)
          for (int j = 0; j < MAX; j++)
            dp[i, j] = -1;
    }
 
    // Function to find non-decreasing
    // sequence of size k with minimum sum
    static int solve(int[] arr, int i, int k)
    {
        int ans = 0;
         
        // If already computed
        if (dp[i, k] != -1)
            return dp[i, k];
 
        // Corner cases
        if (i < 0)
            return inf;
        if (k == 1)
        {
            ans = inf;
            for (int j = 0; j <= i; j++)
            ans = Math.Min(ans, arr[i]);
            return ans;
        }
 
        // Recursive computation
        ans = inf;
        for (int j = 0; j < i; j++)
            if (arr[i] >= arr[j])
                ans = Math.Min(ans, Math.Min(solve(arr, j, k),
                               solve(arr, j, k - 1) + arr[i]));
            else
                ans = Math.Min(ans, solve(arr, j, k));
 
        dp[i, k] = ans;
 
        return dp[i, k];
    }
 
    // driver program
    public static void Main()
    {
        initialize();
        int[] a = { 58, 12, 11, 12, 82, 30,
                          20, 77, 16, 86 };
        int n = a.Length;
        int k = 4;
        Console.WriteLine(solve(a, n - 1, k));
    }
}
 
// This code is contributed by vt_m


Javascript


输出:

120

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程