📜  选择K个严格增加的元素的最低成本

📅  最后修改于: 2021-05-06 19:57:06             🧑  作者: Mango

给定一个数组和一个整数K。还给出了另一个数组,该数组存储从第一个数组中选择元素的成本。任务是计算从阵列中选择K个严格增加的元素的最小成本。
例子:

Input: N = 4, K = 2
ele[] = {2, 6, 4, 8}
cost[] = {40, 20, 30, 10}
Output: 30
Explanation:
30 is the minimum cost by selecting elements 
6 and 8 from the array with cost 
10 + 20 respectively

Input: N = 11, K = 4
ele = {2, 6, 4, 8, 1, 3, 15, 9, 22, 16, 45}
cost = {40, 20, 30, 10, 50, 10, 20, 30, 40, 20, 10}
Output: 60
Explanation:
60 is the minimum cost by selecting elements 
3, 15, 16, 45 from the array with cost 
10 + 20 + 20 + 10 respectively

方法:
使用动态编程方法可以轻松解决给定的问题。由于问题要求增加要素,然后要求最小成本,因此很显然,我们必须要么选择第i个要素,要么不选择一个要素,然后计算每个要素的最低成本。
现在,使用一个3D DP数组存储我们的最小成本值,其中cache [i] [prev] [cnt]存储直到第i个元素,prev元素和到目前为止所考虑的数量计数的最小成本。
涉及3个基本条件:

  • 如果计算了k个元素,则返回0。
  • 如果已遍历数组的所有元素,则返回MAX_VALUE。
  • 检查它是否已经在dp数组中计算了。

现在是选择ith元素或不选择ith元素的部分:

  • 当不考虑第ith个元素时ans = dp(i + 1,prev,cnt,s,c)
  • 当第ith个元素大于上一个元素时,检查添加其成本是否使总成本最小ans = min(ans,c [i] + dp(i + 1,i,cnt + 1,s,c))

下面是上述方法的实现:

CPP
// C++ program for
// the above approach
#include 
using namespace std;
 
const int N = 1005;
const int K = 20;
int n, k;
int dp[N + 1][N + 1][K + 1];
 
// Function to calculate
// min cost to choose
// k increasing elements
int minCost(int i, int prev, int cnt,
                    int ele[], int cost[])
{
    // If k elemnets are
    // counted return 0
    if (cnt == k + 1) {
        return 0;
    }
 
    // If all elements
    // of array has been
    // traversed then
    // return MAX_VALUE
    if (i == n + 1) {
        return 1e5;
    }
 
    // To check if this is
    // already calculated
    int& ans = dp[i][prev][cnt];
    if (ans != -1) {
        return ans;
    }
 
    // When i'th elements
    // is not considered
    ans = minCost(i + 1, prev, cnt, ele, cost);
 
    // When the ith element
    // is greater than previous
    // element check if adding
    // its cost makes total cost minimum
    if (ele[i] > ele[prev]) {
        ans = min(ans, cost[i] + minCost(i + 1,
                           i, cnt + 1, ele, cost));
    }
    return ans;
}
 
// Driver code
int main()
{
 
    memset(dp, -1, sizeof(dp));
    n = 4;
    k = 2;
 
    int ele[n + 1] = { 0, 2, 6, 4, 8 };
 
    int cost[n + 1] = { 0, 40, 20, 30, 10 };
 
    int ans = minCost(1, 0, 1, ele, cost);
 
    if (ans == 1e5) {
        ans = -1;
    }
 
    cout << ans << endl;
 
    return 0;
}


Python3
# Python3 program for
# the above approach
N = 1005;
K = 20;
 
n = 0
k = 0
 
dp = [[[-1 for k in range(K + 1)] for j in range(N + 1)] for i in range(N + 1)]
  
# Function to calculate
# min cost to choose
# k increasing elements
def minCost(i, prev, cnt, ele, cost):
 
    # If k elemnets are
    # counted return 0
    if (cnt == k + 1):
        return 0;
      
    # If all elements
    # of array has been
    # traversed then
    # return MAX_VALUE
    if (i == n + 1):
        return 100000;
     
    # To check if this is
    # already calculated
    ans = dp[i][prev][cnt];
     
    if (ans != -1):
        return ans;
     
    # When i'th elements
    # is not considered
    ans = minCost(i + 1, prev, cnt, ele, cost);
  
    # When the ith element
    # is greater than previous
    # element check if adding
    # its cost makes total cost minimum
    if (ele[i] > ele[prev]):
        ans = min(ans, cost[i] + minCost(i + 1, i, cnt + 1, ele, cost));
     
    return ans;
 
# Driver code
if __name__=='__main__':
  
    n = 4;
    k = 2;
  
    ele = [ 0, 2, 6, 4, 8 ]
  
    cost = [ 0, 40, 20, 30, 10 ]
  
    ans = minCost(1, 0, 1, ele, cost);
  
    if (ans == 100000):
        ans = -1;
     
    print(ans)
  
# This code is contributed by rutvik_56


输出:
30