给定数字N,任务是通过执行以下操作从1个块构建N个块:
- 容器中存在的块数加倍,此操作的成本为
X
- 将容器中存在的块数增加1,此操作的成本为
Y
- 将容器中存在的块数减少一个,此操作的成本为
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
块的成本最低。我们执行任何其他操作都必须增加与您无关的最佳成本。所以当我什至是递归关系时: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