给定一个由 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 现场工作专业课程和学生竞争性编程现场课程。