高度为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 次。我们可以使用 count for n-1 递归计算 n 的计数。
这个想法是使用动态规划。声明一个二维数组 dp[][],其中每个状态 dp[i][j] 使用从 j 到 m 的数字表示长度为 i 的递减序列的数量。我们需要注意一个数字可以在大部分时间使用的事实。这可以通过考虑一个数字出现 1 到 k 次来完成。因此,我们的递推关系变为:
此外,我们可以使用以下事实:对于固定的 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
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。