📌  相关文章
📜  带有最小和的大小为k的非递减子序列

📅  最后修改于: 2021-04-26 08:27:43             🧑  作者: 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)为大小为k的索引为i的子序列的最小和。然后将有两种状态:
1.包括当前元素。 {solve(j,k-1)+ a [i]}
2.排除当前元素。 {solve(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


120