📌  相关文章
📜  构造数字成本之和为 K 的最大数

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

给定一个正整数K和一个由N( =9) 个整数组成的数组arr[] ,使得arr[i]表示数字(i+1)的成本,任务是找到可以形成的最大数使用范围[1, 9] 上的数字,使得所形成数字的数字成本之和为K

例子:

方法:根据以下观察可以解决给定的问题:

  1. 问题是 0/1 Unbounded Knapsack 的变体 因为选择形成最大数字的数字也可以重复,并且它们的成本总和必须是K
  2. 因此,想法是重复包含或排除每个可能的数字以形成最大数字并打印所有可能组合后获得的最大数字。
  3. 上面的想法可以根据下面的递归关系来实现:
    • 在每一步跟踪用于形成数字的数字和剩余的总和K。
    • 递推关系的基本条件是:
      1. 如果总和K变为0 ,则这将导致形成的数字组合之一。
      2. 如果K为负数或遍历所有数组,则不可能形成任何成本总和为K 的数字
    • 在每一步,首先包含然后排除任何数字D并递归调用函数,分别具有更新的剩余成本K。

请按照以下步骤解决给定的问题:

  • 初始化dp[][]大小为10*K 的二维数组,这样dp[i][j]存储通过使用具有总和j的前i 个数字形成的最大数字。
  • 定义一个递归函数,比如recursion(i, K)其中 起始索引,总和K ,并执行以下步骤:
    1. 将基本情况定义为
      • 如果总和K的值变为0 ,则从函数返回一个空字符串作为数字成本总和已形成的数字。
      • 如果和K 的值小于0i等于N,则从函数返回“0” ,因为无法形成数字。
    2. 如果已经计算了当前状态dp[i][N] ,则从函数返回该值。
    3. 将通过包含当前数字i+1获得的结果存储为to_string(i+1) + recursion(0, K – arr[D])变量,例如include
    4. 将排除当前数字i+1得到的结果作为递归(i+1, K – arr[D]) 存储在变量中,比如exclude。
  • 将当前 DP 状态dp[i][K] 更新max(include, exclude)并从函数返回此值。
  • 完成上述步骤后,调用递归函数recursion(0, K)并检查返回的字符串是否为空,然后打印“0” 。否则,将返回的字符串打印为形成的结果最大数。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include "bits/stdc++.h"
using namespace std;
 
// Function to find the maximum number
// among the two numbers S and T
string getMaximum(string& S, string& T)
{
    // If "0" exists in the string S
    if (S.find("0") != string::npos)
        return T;
 
    // If "0" exists in the string T
    if (T.find("0") != string::npos)
        return S;
 
    // Else return the maximum number
    // formed
    return (S.length() > T.length() ? S : T);
}
 
// Recursive function to find maximum
// number formed such that the sum of
// cost of digits of formed number is K
string recursion(int arr[], int idx,
                 int N, int K,
                 vector >& dp)
{
    // Base Case
    if (K == 0) {
        return "";
    }
    if (K < 0 or idx == N) {
        return "0";
    }
 
    // Return the stored state
    if (dp[idx][K] != "-1")
        return dp[idx][K];
 
    // Including the digit (idx + 1)
    string include
        = to_string(idx + 1)
          + recursion(arr, 0, N,
                      K - arr[idx], dp);
 
    // Excluding the digit (idx + 1)
    string exclude = recursion(
        arr, idx + 1, N, K, dp);
 
    // Store the result and return
    return dp[idx][K] = getMaximum(
               include, exclude);
}
 
// Function to find the maximum number
// formed such that the sum of the cost
// digits in the formed number is K
string largestNumber(int arr[], int N, int K)
{
    // Stores all Dp-states
    vector > dp(
        N + 1, vector(K + 1,
                              "-1"));
 
    // Recursive Call
    string ans = recursion(arr, 0, N,
                           K, dp);
 
    // Return the result
    return (ans == "" ? "0" : ans);
}
 
// Driver Code
int main()
{
    int arr[] = { 3, 12, 9, 5, 3, 4, 6, 5, 10 };
    int K = 14;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << largestNumber(arr, N, K);
 
    return 0;
}


Python3
# Python program for the above approach
 
# Function to find the maximum number
# among the two numbers S and T
def getMaximum(S, T):
 
  # If "0" exists in the string S
  if (S.count("0") > 0):
      return T;
 
  # If "0" exists in the string T
  if (T.count("0") > 0):
      return S;
 
  # Else return the maximum number
  # formed
  return S if len(S) > len(T) else T;
 
# Recursive function to find maximum
# number formed such that the sum of
# cost of digits of formed number is K
def recursion(arr, idx, N, K, dp):
 
  # Base Case
    if (K == 0):
        return "";
 
    if (K < 0 or idx == N):
        return "0";
 
    # Return the stored state
    if (dp[idx][K] != "-1"):
        return dp[idx][K];
 
    # Including the digit (idx + 1)
    include = str(idx + 1) + recursion(arr, 0, N, K - arr[idx], dp);
 
    # Excluding the digit (idx + 1)
    exclude = recursion(arr, idx + 1, N, K, dp);
 
    # Store the result and return
    dp[idx][K] = getMaximum(include, exclude)
    return (dp[idx][K])
 
 
# Function to find the maximum number
# formed such that the sum of the cost
# digits in the formed number is K
def largestNumber(arr, N, K):
 
    # Stores all Dp-states
    dp = [["-1" for i in range(K + 1)] for i in range(N + 1)]
 
    # Recursive Call
    ans = recursion(arr, 0, N, K, dp);
 
    # Return the result
    return "0" if ans == "" else ans;
 
# Driver Code
arr = [3, 12, 9, 5, 3, 4, 6, 5, 10];
K = 14;
N = len(arr);
 
print(largestNumber(arr, N, K));
 
# This code is contributed by _saurabh_jaiswal.


Javascript


输出:
8555

时间复杂度: O(9*K 2 )
辅助空间: O(9*K)