📜  从一个块构建 N 个块的最低成本

📅  最后修改于: 2021-09-22 10:36:57             🧑  作者: Mango

给定一个数字 N,任务是通过执行以下操作从 1 个块构建 N 个块:

  1. 将容器中存在的块数加倍,此操作的成本为X
  2. 将容器中存在的块数增加 1,此操作的成本为Y
  3. 将容器中存在的块数减少 1,此操作的成本为Z

例子:

方法:

  • 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 现场工作专业课程学生竞争性编程现场课程