给定形式的元素的无限个和 (n> = 0)。任务是找到所选元素的最小数量,以使总和等于K。
例子:
Input : K = 48
Output : 6
elements chosen are: (1 + 1 + 1 + 10 + 10 + 25)
Input : 69
Output : 9
elements chosen are: (1 + 1 + 1 + 1 + 10 + 10 + 10 + 10 + 25)
方法:
以下元素数量不限:
1、10、25、100、1000、2500、10000、100000、250000…等等。
贪婪方法在这里行不通。对于K = 66,通过贪婪方法最小计数将是9和选择元件25 + 25 + 10 + 1 + 1 + 1 + 1 + 1 + 1 = 66。但是,其最佳答案是6时这些元件选自:25 + 10 + 10 + 10 + 10 + 1 =66。因此,动态编程将在此处工作。但是不能应用简单的DP,因为K可以达到10 ^ 9。
动态编程方法:
- 预先计算最小编号所选择的构成总和最多为99的元素并将其存储在备忘录数组中。
- 同样,最多只能由1、10和25的组合来形成总和为99。
- 从K的末尾开始,对每最后2位数字进行迭代以找到最小编号。所选元素的总和为最后两位数。
- 将它们全部求和以找到最小数量。
Illustration of the above approach:
Let’s take K = 250166
Let min_count = 0, last 2 digits = 66
add minimum number of elements to min_count that sums to 66 (it is calculated from memo array
that we have precomputed).
min_count = min_count + 6,
Now, min_count = 6, last 2 digits = 01
add minimum number of elements to min_count sums to 1.
min_count = min_count + 1,
Now, min_count = 7, last 2 digits = 25
add minimum number of elements to min_count sums to 25.
min_count = min_count + 1,
Now, min_count = 8.
So, minimum number of elements chosen that sums to 250166 is 8.
Optimal chosen Elements are (250000, 100, 25, 10, 10, 10, 10, 1)
下面是上述方法的实现。
C++
// C++ implementation of the above approach
#include
using namespace std;
int minCount(int K)
{
// we will only store min counts
// of sum upto 100
int memo[100];
// initialize with INT_MAX
for (int i = 0; i < 100; i++) {
memo[i] = INT_MAX;
}
// memo[0] = 0 as 0 is
// made from 0 elements
memo[0] = 0;
// fill memo array with min counts
// of elements that will constitute
// sum upto 100
for (int i = 1; i < 100; i++) {
memo[i] = min(memo[i - 1] + 1, memo[i]);
}
for (int i = 10; i < 100; i++) {
memo[i] = min(memo[i - 10] + 1, memo[i]);
}
for (int i = 25; i < 100; i++) {
memo[i] = min(memo[i - 25] + 1, memo[i]);
}
// min_count will store min
// count of elements chosen
long min_count = 0;
// starting from end iterate over
// each 2 digits and add min count
// of elements to min_count
while (K > 0) {
min_count += memo[K % 100];
K /= 100;
}
return min_count;
}
// Driver code
int main()
{
int K = 69;
cout << minCount(K) << endl;
return 0;
}
Java
// Java implementation of the above approach
class GFG
{
static int minCount(int K)
{
// we will only store min counts
// of sum upto 100
int memo[] = new int[100];
// initialize with INT_MAX
for (int i = 0; i < 100; i++)
{
memo[i] = Integer.MAX_VALUE;
}
// memo[0] = 0 as 0 is
// made from 0 elements
memo[0] = 0;
// fill memo array with min counts
// of elements that will constitute
// sum upto 100
for (int i = 1; i < 100; i++)
{
memo[i] = Math.min(memo[i - 1] + 1, memo[i]);
}
for (int i = 10; i < 100; i++)
{
memo[i] = Math.min(memo[i - 10] + 1, memo[i]);
}
for (int i = 25; i < 100; i++)
{
memo[i] = Math.min(memo[i - 25] + 1, memo[i]);
}
// min_count will store min
// count of elements chosen
int min_count = 0;
// starting from end iterate over
// each 2 digits and add min count
// of elements to min_count
while (K > 0)
{
min_count += memo[K % 100];
K /= 100;
}
return min_count;
}
// Driver code
public static void main (String[] args)
{
int K = 69;
System.out.println(minCount(K));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation of the above approach
def minCount(K):
# we will only store min counts
# of sum upto 100
memo=[10**9 for i in range(100)]
# memo[0] = 0 as 0 is
# made from 0 elements
memo[0] = 0
# fill memo array with min counts
# of elements that will constitute
# sum upto 100
for i in range(1,100):
memo[i] = min(memo[i - 1] + 1, memo[i])
for i in range(10,100):
memo[i] = min(memo[i - 10] + 1, memo[i])
for i in range(25,100):
memo[i] = min(memo[i - 25] + 1, memo[i])
# min_count will store min
# count of elements chosen
min_count = 0
# starting from end iterate over
# each 2 digits and add min count
# of elements to min_count
while (K > 0):
min_count += memo[K % 100]
K //= 100
return min_count
# Driver code
K = 69
print(minCount(K))
# This code is contributed by mohit kumar 29
C#
// C# implementation of the above approach
using System;
class GFG
{
static int minCount(int K)
{
// we will only store min counts
// of sum upto 100
int []memo = new int[100];
// initialize with INT_MAX
for (int i = 0; i < 100; i++)
{
memo[i] = int.MaxValue;
}
// memo[0] = 0 as 0 is
// made from 0 elements
memo[0] = 0;
// fill memo array with min counts
// of elements that will constitute
// sum upto 100
for (int i = 1; i < 100; i++)
{
memo[i] = Math.Min(memo[i - 1] + 1, memo[i]);
}
for (int i = 10; i < 100; i++)
{
memo[i] = Math.Min(memo[i - 10] + 1, memo[i]);
}
for (int i = 25; i < 100; i++)
{
memo[i] = Math.Min(memo[i - 25] + 1, memo[i]);
}
// min_count will store min
// count of elements chosen
int min_count = 0;
// starting from end iterate over
// each 2 digits and add min count
// of elements to min_count
while (K > 0)
{
min_count += memo[K % 100];
K /= 100;
}
return min_count;
}
// Driver code
static public void Main ()
{
int K = 69;
Console.WriteLine(minCount(K));
}
}
// This code is contributed by ajit
9