📌  相关文章
📜  大小为 P 的有效数组的计数,其中元素在 [1, N] 范围内具有至少 M 距离的重复项

📅  最后修改于: 2022-05-13 01:56:04.668000             🧑  作者: Mango

大小为 P 的有效数组的计数,其中元素在 [1, N] 范围内具有至少 M 距离的重复项

给定三个整数N、MP ,任务是找到可以创建的大小为P且每个元素在[1, N] 范围内的有效数组的总数,使得重复项至少相隔 M距离。

示例

方法:问题可以在动态规划的帮助下解决,

  • 在每个索引处有两种可能的选择是:要么我们追加已使用的元素,相距至少 M距离要么我们追加一个新元素并减少未使用字符的数量。
  • 要处理这个问题,请使用递归动态编程
  • 要加快递归调用,请使用记忆化,以便不再计算已计算的状态。
  • 每一步都有两个选项:
    1. 选择之前出现的元素,j 和 k 不会改变,因为使用和未使用的元素的数量不会改变: dp[i+1][j][k]
    2. 选择从未使用过的元素,此时使用的字符数加1,未使用的字符数减1: dp[i+1][j+1][k-1]

dp[i][j][k]将是上述两个步骤的总和,表示为:

  • 最终答案将是dp[0][0][N]。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to calculate the total
// number of arrays
int calculate(int position, int used, int unused, int P,
              int M, vector > >& dp)
{
    // If the size of the array is P
    if (position == P) {
        // Check if all elements are
        // used atlease once
        return unused == 0 ? 1 : 0;
    }
 
    // Check if this state is already
    // calculated
    if (dp[position][used][unused] != -1)
        return dp[position][used][unused];
 
    // Initialize the result
    int result = 0;
 
    // Use a number from the list of
    // unused numbers
    if (unused > 0) {
        // There are 'unused' number of
        // favourable choices
        result += calculate(position + 1, used + 1,
                            unused - 1, P, M, dp)
                  * unused;
    }
 
    // Use a number from already present number
    // atlease M distance back
    if (used > M) {
        // There are 'used - M' number of
        // favourable choices
        result += calculate(position + 1,
                            used, unused, P,
                            M, dp)
                  * (used - M);
    }
 
    // Store the result
    return dp[position][used][unused] = result;
}
 
// Function to solve the problem
int solve(int N, int P, int M)
{
    // Initialize DP table : dp[i][j][j]
    // i : current position/index
    // j : number of used elements
    // k : number of unused elements
    vector > > dp(
        101,
        vector >(101,
                             vector(101, -1)));
 
    return calculate(0, 0, N, P, M, dp);
}
// Driver Code
int main()
{
    int N = 2, M = 0, P = 3;
    cout << solve(N, P, M);
}


Java
// Java program for the above approach
import java.io.*;
class GFG
{
 
  // Function to calculate the total
  // number of arrays
  static int calculate(int position, int used, int unused, int P,
                       int M, int dp[][][])
  {
    // If the size of the array is P
    if (position == P)
    {
       
      // Check if all elements are
      // used atlease once
      return unused == 0 ? 1 : 0;
    }
 
    // Check if this state is already
    // calculated
    if (dp[position][used][unused] != -1)
      return dp[position][used][unused];
 
    // Initialize the result
    int result = 0;
 
    // Use a number from the list of
    // unused numbers
    if (unused > 0) {
      // There are 'unused' number of
      // favourable choices
      result += calculate(position + 1, used + 1,
                          unused - 1, P, M, dp)
        * unused;
    }
 
    // Use a number from already present number
    // atlease M distance back
    if (used > M)
    {
       
      // There are 'used - M' number of
      // favourable choices
      result += calculate(position + 1,
                          used, unused, P,
                          M, dp)
        * (used - M);
    }
 
    // Store the result
    return dp[position][used][unused] = result;
  }
 
  // Function to solve the problem
  static int solve(int N, int P, int M)
  {
    // Initialize DP table : dp[i][j][j]
    // i : current position/index
    // j : number of used elements
    // k : number of unused elements
    int[][][] dp = new int[101][101][101];
    for(int i = 0; i < 101; i++)
    {
      for(int j = 0; j < 101; j++)
        for(int k = 0; k < 101; k++)
          dp[i][j][k] = -1;
    }
    return calculate(0, 0, N, P, M, dp);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int N = 2, M = 0, P = 3;
    System.out.println(solve(N, P, M));
  }
}
 
// This code is contributed by dwivediyash


Python3
# Python 3 program for the above approach
 
# Function to calculate the total
# number of arrays
def calculate(position, used, unused, P, M, dp):
   
    # If the size of the array is P
    if (position == P):
       
        # Check if all elements are
        # used atlease once
        if unused == 0:
          return 1
        else:
          return 0
 
    # Check if this state is already
    # calculated
    if (dp[position][used][unused] != -1):
        return dp[position][used][unused]
 
    # Initialize the result
    result = 0
 
    # Use a number from the list of
    # unused numbers
    if (unused > 0):
       
        # There are 'unused' number of
        # favourable choices
        result += calculate(position + 1, used + 1,unused - 1, P, M, dp)* unused
 
    # Use a number from already present number
    # atlease M distance back
    if (used > M):
       
        # There are 'used - M' number of
        # favourable choices
        result += calculate(position + 1,used, unused, P,M, dp)* (used - M)
    dp[position][used][unused] = result
 
    # Store the result
    return dp[position][used][unused]
 
# Function to solve the problem
def solve(N, P, M):
   
    # Initialize DP table : dp[i][j][j]
    # i : current position/index
    # j : number of used elements
    # k : number of unused elements
    dp = [[[-1 for i in range(101)] for i in range(101)] for j in range(101)]
 
    return calculate(0, 0, N, P, M, dp)
 
# Driver Code
if __name__ == '__main__':
    N = 2
    M = 0
    P = 3
    print(solve(N, P, M))
     
    # This code is contributed by SURENDRA_GANGWAR.


C#
// C# program for the above approach
using System;
 
public class GFG
{
 
  // Function to calculate the total
  // number of arrays
  static int calculate(int position, int used, int unused, int P,
                       int M, int [,,]dp)
  {
     
    // If the size of the array is P
    if (position == P)
    {
       
      // Check if all elements are
      // used atlease once
      return unused == 0 ? 1 : 0;    
    }
 
    // Check if this state is already
    // calculated
    if (dp[position,used,unused] != -1)
      return dp[position,used,unused];
 
    // Initialize the result
    int result = 0;
 
    // Use a number from the list of
    // unused numbers
    if (unused > 0)
    {
       
      // There are 'unused' number of
      // favourable choices
      result += calculate(position + 1, used + 1,
                          unused - 1, P, M, dp)
        * unused;
    }
 
    // Use a number from already present number
    // atlease M distance back
    if (used > M)
    {
       
      // There are 'used - M' number of
      // favourable choices
      result += calculate(position + 1,
                          used, unused, P,
                          M, dp)
        * (used - M);
    }
 
    // Store the result
    return dp[position,used,unused] = result;
  }
 
  // Function to solve the problem
  static int solve(int N, int P, int M)
  {
     
    // Initialize DP table : dp[i,j,j]
    // i : current position/index
    // j : number of used elements
    // k : number of unused elements
    int[,,] dp = new int[101,101,101];
    for(int i = 0; i < 101; i++)
    {
      for(int j = 0; j < 101; j++)
        for(int k = 0; k < 101; k++)
          dp[i, j, k] = -1;
    }
    return calculate(0, 0, N, P, M, dp);
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int N = 2, M = 0, P = 3;
    Console.WriteLine(solve(N, P, M));
  }
}
 
// This code is contributed by shikhasingrajput


Javascript



输出
6

时间复杂度:O(NMP) (因为三个因变量)

辅助空间:O(NMP) (DP矩阵的大小)