给定一个数字 N,任务是通过执行以下操作从 1 个块构建 N 个块:
- 将容器中存在的块数加倍,此操作的成本为
X
。 - 将容器中存在的块数增加 1,此操作的成本为
Y
。 - 将容器中存在的块数减少 1,此操作的成本为
Z
例子:
Input: N = 5, X = 2, Y = 1, Z = 3
Output: 4
Explanation:
In the first operation just increase the number of blocks by one, cost = 1 and block count = 2
In the second operation double the blocks, cost = 3 and block count = 4
In the third operation again increase the number_of_blocks by one, cost = 4 and block count = 5
So minimum cost = 4
Input: N = 7, X = 1, Y = 7, Z = 2
Output: 5
方法:
- 让
f(i)
表示构建i
个块的最小成本。所以f(i)
=min(f(2*i)+X, f(i-1)+Y, f(i+1)+Z)
这里当前值取决于它的下一个值以及它的前一个值,但你知道在动态编程中当前值只取决于它的前一个值。所以尝试将它的下一个值转换为它的前一个值。我们可以将f(2*i)
写为f(i/2)
因为当我们已经构建了 i/2 个块时,我们可以将当前块的数量加倍或将块数量增加 1 或将块数量减少 1 . 这里不需要计算f(2*i)
。
现在f(i) = min(f(i/2)+X, f(i-1)+Y, f(i+1)+Z)
- 如果
i
是偶数,那么(i+1)
一定是奇数。我们可以只通过执行递增操作和双重操作来构建(i)
块,所以你不需要执行递减操作,为什么?
这是因为(i+1)
是奇数。所以如果您通过执行增量操作构建(i+1)
个块,那么可以确认我们已经构建了i
个块,这意味着我们构建i
块的成本最低。如果我们执行任何其他操作,它必须增加您的最佳成本,这是无关紧要的。所以当 i 为偶数时的递推关系:f(i)=min(f(i/2)+X, f(i-1)+Y)
- 如果
i
是奇数,则(i+1)
必须是偶数。我们只能通过执行双操作或递减操作来构建(i+1)
个块,为什么不进行递增操作?
这是因为如果您已经构建了i
个块,则无需构建(i+1)
个块,因为它会增加更多成本。所以我们可以计算出f(i+1)=f((i+1)/2)+ X.
所以当i为奇数时的递推关系:f(i)=min(f(i-1)+Y, f( (i+1)/2)+X+Z)
下面是上述方法的实现:
CPP
// C++ program to Minimum cost // to build N blocks from one block #include
using namespace std; // Function to calculate // min cost to build N blocks int minCost(int n, int x, int y, int z) { int dp[n + 1] = { 0 }; // Initialize base case dp[0] = dp[1] = 0; for (int i = 2; i <= n; i++) { // Recurence when // i is odd if (i % 2 == 1) { dp[i] = min( dp[(i + 1) / 2] + x + z, dp[i - 1] + y); } // Recurence when // i is even else { dp[i] = min(dp[i / 2] + x, dp[i - 1] + y); } } return dp[n]; } // Driver code int main() { int n = 5, x = 2, y = 1, z = 3; cout << minCost(n, x, y, z) << endl; return 0; }
Java
// Java program to Minimum cost // to build N blocks from one block class GFG { // Function to calculate // min cost to build N blocks static int minCost(int n, int x, int y, int z) { int dp[] = new int[n + 1]; // Initialize base case dp[0] = dp[1] = 0; for (int i = 2; i <= n; i++) { // Recurence when // i is odd if (i % 2 == 1) { dp[i] = Math.min( dp[(i + 1) / 2] + x + z, dp[i - 1] + y); } // Recurence when // i is even else { dp[i] = Math.min(dp[i / 2] + x, dp[i - 1] + y); } } return dp[n]; } // Driver code public static void main(String[] args) { int n = 5, x = 2, y = 1, z = 3; System.out.print(minCost(n, x, y, z) +"\n"); } } // This code is contributed by Rajput-Ji
Python
# python3 program to Minimum cost # to build N blocks from one block # Function to calculate # min cost to build N blocks def minCost(n, x, y, z): dp = [0] * (n + 1) # Initialize base case dp[0] = dp[1] = 0 for i in range(2, n + 1): # Recurence when # i is odd if (i % 2 == 1): dp[i] = min(dp[(i + 1) // 2] + x + z, dp[i - 1] + y) # Recurence when # i is even else: dp[i] = min(dp[i // 2] + x, dp[i - 1] + y) return dp[n] # Driver code n = 5 x = 2 y = 1 z = 3 print(minCost(n, x, y, z)) # This code is contributed by mohit kumar 29
C#
// C# program to Minimum cost // to build N blocks from one block using System; class GFG { // Function to calculate // min cost to build N blocks static int minCost(int n, int x, int y, int z) { int []dp = new int[n + 1]; // Initialize base case dp[0] = dp[1] = 0; for (int i = 2; i <= n; i++) { // Recurence when // i is odd if (i % 2 == 1) { dp[i] = Math.Min( dp[(i + 1) / 2] + x + z, dp[i - 1] + y); } // Recurence when // i is even else { dp[i] = Math.Min(dp[i / 2] + x, dp[i - 1] + y); } } return dp[n]; } // Driver code public static void Main(String[] args) { int n = 5, x = 2, y = 1, z = 3; Console.Write(minCost(n, x, y, z) +"\n"); } } // This code is contributed by PrinciRaj1992
输出:4
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。