📜  瓷砖堆叠问题

📅  最后修改于: 2021-06-25 13:31:10             🧑  作者: Mango

高度为n的稳定塔是这样一种塔,它由正好垂直堆叠的n个单位高度的瓷砖组成,这样就不会在较小的瓷砖上放置较大的瓷砖。一个例子如下所示 :

我们有无数个大小为1、2,…,m的图块。任务是计算可以从这些图块构建的高度为n的不同稳定塔的数量,但要限制在塔中最多只能使用每种大小的k个图块。
注意:当且仅当高度为h(1 <= h <= n)时,两个高度为n的塔才是不同的,以使两个塔在高度h处具有不同大小的图块。
例子:

Input : n = 3, m = 3, k = 1.
Output : 1
Possible sequences: { 1, 2, 3}. 
Hence answer is 1.

Input : n = 3, m = 3, k = 2.
Output : 7
{1, 1, 2}, {1, 1, 3}, {1, 2, 2},
{1, 2, 3}, {1, 3, 3}, {2, 2, 3}, 
{2, 3, 3}.

我们基本上需要使用从1到m的数字来计数长度为n的递减序列,其中每个数字最多可以使用k次。我们可以使用n-1的计数递归计算n的计数。
这个想法是使用动态编程。声明2D数组dp [] [],其中每个状态dp [i] [j]均使用从j到m的数字表示长度为i的递减序列数。我们需要注意一个事实,即在k的大部分时间内都可以使用数字。这可以通过考虑1到k个数字出现来完成。因此,我们的递归关系变为:
{\huge DP[i][j] = \sum_{x=0}^{k}[i-x][j-1]}
同样,我们可以使用以下事实:对于固定的j,我们使用i的前k个值的连续值。因此,我们可以为每个状态维护一个前缀和数组。现在我们摆脱了每个状态的k因子。
下面是此方法的实现:

C++
// CPP program to find number of ways to make stable
// tower of given height.
#include 
using namespace std;
#define N 100
 
int possibleWays(int n, int m, int k)
{
    int dp[N][N];
    int presum[N][N];
    memset(dp, 0, sizeof dp);
    memset(presum, 0, sizeof presum);
 
    // Initialing 0th row to 0.
    for (int i = 1; i < n + 1; i++) {
        dp[0][i] = 0;
        presum[0][i] = 1;
    }
 
    // Initialing 0th column to 0.
    for (int i = 0; i < m + 1; i++)
        presum[i][0] = dp[i][0] = 1;
 
    // For each row from 1 to m
    for (int i = 1; i < m + 1; i++) {
 
        // For each column from 1 to n.
        for (int j = 1; j < n + 1; j++) {
 
            // Initialing dp[i][j] to presum of (i - 1, j).
            dp[i][j] = presum[i - 1][j];
            if (j > k) {
                dp[i][j] -= presum[i - 1][j - k - 1];
            }
        }
 
        // Calculating presum for each i, 1 <= i <= n.
        for (int j = 1; j < n + 1; j++)
            presum[i][j] = dp[i][j] + presum[i][j - 1];
    }
 
    return dp[m][n];
}
 
// Driver Program
int main()
{
    int n = 3, m = 3, k = 2;
    cout << possibleWays(n, m, k) << endl;
    return 0;
}


Java
// Java program to find number of ways to make
// stable tower of given height.
class GFG
{
 
    static int N = 100;
 
    static int possibleWays(int n, int m, int k)
    {
        int[][] dp = new int[N][N];
        int[][] presum = new int[N][N];
 
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                dp[i][j] = 0;
                presum[i][j] = 0;
            }
        }
 
        // Initialing 0th row to 0.
        for (int i = 1; i < n + 1; i++)
        {
            dp[0][i] = 0;
            presum[0][i] = 1;
        }
 
        // Initialing 0th column to 0.
        for (int i = 0; i < m + 1; i++)
        {
            presum[i][0] = dp[i][0] = 1;
        }
 
        // For each row from 1 to m
        for (int i = 1; i < m + 1; i++)
        {
 
            // For each column from 1 to n.
            for (int j = 1; j < n + 1; j++)
            {
 
                // Initialing dp[i][j] to presum of (i - 1, j).
                dp[i][j] = presum[i - 1][j];
                if (j > k)
                {
                    dp[i][j] -= presum[i - 1][j - k - 1];
                }
            }
 
            // Calculating presum for each i, 1 <= i <= n.
            for (int j = 1; j < n + 1; j++) {
                presum[i][j] = dp[i][j] + presum[i][j - 1];
            }
        }
 
        return dp[m][n];
    }
 
    // Driver Program
    public static void main(String[] args) {
        int n = 3, m = 3, k = 2;
        System.out.println(possibleWays(n, m, k));
    }
}
// This code has been contributed by 29AjayKumar


Python 3
# Python3 code to find number of ways
# to make stable tower of given height
n = 100
def possibleWays(n, m, k):
    dp = [[0 for i in range(10)]
             for j in range(10)]
    presum=[[0 for i in range(10)]
               for j in range(10)]
     
    # initialing 0th row to 0
    for i in range(1, n + 1):
        dp[0][i] = 0
        presum[0][i] = 1
     
    # initialing 0th column to 0
    for i in range(0, m + 1):
        presum[i][0] = 1
        dp[i][0] = 1
     
    # for each from 1 to m
    for i in range(1, m + 1):
         
        # for each column from 1 to n.
        for j in range(1, n + 1):
             
            # for each column from 1 to n
            # Initialing dp[i][j] to presum
            # of (i-1,j).
            dp[i][j] = presum[i - 1][j]
            if j > k:
                dp[i][j] -= presum[i - 1][j - k - 1]
                 
        for j in range(1, n + 1):
            presum[i][j] = dp[i][j] + presum[i][j - 1]
         
    return dp[m][n]
     
# Driver Code
n, m, k = 3, 3, 2
 
print(possibleWays(n, m, k))
 
# This code is contributed
# by Mohit kumar 29


C#
// C# program to find number of ways to make
// stable tower of given height.
using System;
 
class GFG
{
    static int N = 100 ;
 
    static int possibleWays(int n, int m, int k)
    {
        int[,] dp = new int[N, N];
        int[,] presum = new int[N, N];
         
        for(int i = 0; i < N; i++)
        {
            for(int j = 0; j < N; j++)
            {
                dp[i, j] = 0;
                presum[i, j] = 0;
            }
        }
     
        // Initialing 0th row to 0.
        for (int i = 1; i < n + 1; i++)
        {
            dp[0, i] = 0;
            presum[0, i] = 1;
        }
     
        // Initialing 0th column to 0.
        for (int i = 0; i < m + 1; i++)
            presum[i, 0] = dp[i, 0] = 1;
     
        // For each row from 1 to m
        for (int i = 1; i < m + 1; i++)
        {
     
            // For each column from 1 to n.
            for (int j = 1; j < n + 1; j++)
            {
     
                // Initialing dp[i][j] to presum of (i - 1, j).
                dp[i, j] = presum[i - 1, j];
                if (j > k)
                {
                    dp[i, j] -= presum[i - 1, j - k - 1];
                }
            }
     
            // Calculating presum for each i, 1 <= i <= n.
            for (int j = 1; j < n + 1; j++)
                presum[i, j] = dp[i, j] + presum[i, j - 1];
        }
     
        return dp[m, n];
    }
     
    // Driver Program
    static void Main()
    {
        int n = 3, m = 3, k = 2;
        Console.Write(possibleWays(n, m, k));
    }
}
 
// This code is contributed by DrRoot_
PHP  $k) { 
                $dp[$i][$j] -= $presum[$i - 1][$j - $k - 1]; 
            } 
        } 

        // Calculating presum for each i, 1 <= i <= n. 
        for ($j = 1; $j < $n + 1; $j++) 
            $presum[$i][$j] = $dp[$i][$j] + $presum[$i][$j - 1]; 
    } 

    return $dp[$m][$n]; 
} 

    // Driver Program 
    $n = 3 ;
    $m = 3 ;
    $k = 2; 
    echo possibleWays($n, $m, $k) ; 
    
    # this code is contributed by Ryuga    
?>


Javascript


输出:

7