📜  生成给定字符串的任何排列的最低成本

📅  最后修改于: 2021-05-25 03:01:36             🧑  作者: Mango

给定大小为N的字符串str ,由前N个字母和大小为N * N的矩阵mat []组成,其中mat [i] [j]表示将字符中的i字符放置在字符串j字符之前的开销。该任务是找到生成给定字符串的任何排列的最低成本。

例子:

幼稚的方法:幼稚的想法是生成给定字符串的所有可能排列,并找出每个排列的代价。然后在所有可能的成本中打印最低成本。

时间复杂度: O(N * N!)
辅助空间: O(N!)

高效的方法:为了优化上述方法,其思想是使用带位屏蔽的动态编程。请注意,所有字符都是不同的,并且只能有26个字母。因此,请使用遮罩存储每个字符的存在。步骤如下:

  1. 遍历字符串的所有字符,并将每个字符放置在每个位置(如果可用),即在掩码中设置该位。
  2. 然后,将字符放置在当前位置并计算放置字符的成本。
  3. 通过翻转当前字符的位移动到下一个位置。
  4. 在每次迭代中,掩码代表当前位置的可用字符数。
  5. 完成上述步骤后,在所有计算出的成本中打印最低成本。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function that returns true
// if the current bit is set
bool check(int mask, int i)
{
    int c = (mask & (1 << i));
    return c != 0;
}
 
// Function to find the minimum cost
// to form any permutation of string s
int solve(vector> a, string s,
          int n, int prev, int mask,
          vector> dp)
{
     
    // Base Case
    if (mask == 0)
        return 0;
 
    // Return the precomputed state
    if (dp[mask][prev + 1] != -1)
        return dp[mask][prev + 1];
 
    int ans = 10000;
 
    // Iterate over the string and
    // check all possible characters
    // available for current position
    for(int i = 0; i < s.length(); i++)
    {
        int id = s[i] - 'a';
         
        // Check if character can be
        // placed at current position
        if (check(mask, id))
        {
             
            // As there is no previous
            // character so the cost
            // for 1st character is 0
            if (prev == -1)
            {
                ans = min(ans, solve(a, s, n, id,
                                     mask ^ (1 << id), dp));
            }
 
            // Find the cost of current
            // character and move to next
            // position
            else
            {
                ans = min(ans, a[prev][id] +
                          solve(a, s, n, id,
                                mask ^ (1 << id), dp));
            }
        }
    }
 
    // Store the answer for each
    // current state
    dp[mask][prev + 1] = ans;
    return ans;
}
 
// Function that generates any
// permutation of the given
// string with minimum cost
void generatePermutation(int mask, int n,
                         vector> a,
                         string s)
{
     
    // Initialize dp table
    vector> dp((1 << n) + 5 ,
           vector (n + 5, -1));
 
    // Set all the bits of the
    // current character id
    for(int i = 0; i < s.length(); i++)
    {
        int id = s[i] - 'a';
        mask |= (1 << id);
    }
     
    // Minimum cost of generating
    // the permutation
    cout << solve(a, s, n, -1, mask, dp)
         << endl;
}
 
// Driver Code  
int main()
{
    int N = 5;
    string str = "abcde";
 
    vector> mat = { { 0, 5, 1, 5, 3 },
                                { 4, 0, 9, 4, 2 },
                                { 7, 9, 0, 10, 7 },
                                { 1, 2, 8, 0, 2 },
                                { 3, 9, 7, 7, 0 } };
 
    // Function Call
    generatePermutation(0, N, mat, str);
     
    return 0;
}
 
// This code is contributed by divyeshrabadiya07


Java
// Java program for the above approach
 
import java.util.*;
 
public class Main {
 
    // Function to find the minimum cost
    // to form any permutation of string s
    public static int solve(
        int a[][], String s, int n,
        int prev, int mask, int[][] dp)
    {
        // Base Case
        if (mask == 0)
            return 0;
 
        // Return the precomputed state
        if (dp[mask][prev + 1] != -1)
            return dp[mask][prev + 1];
 
        int ans = 10000;
 
        // Iterate over the string and
        // check all possible characters
        // available for current position
        for (int i = 0; i < s.length(); i++) {
 
            int id = s.charAt(i) - 'a';
 
            // Check if character can be
            // placed at current position
            if (check(mask, id)) {
 
                // As there is no previous
                // character so the cost
                // for 1st character is 0
                if (prev == -1) {
 
                    ans
                        = Math.min(ans,
                                   solve(
                                       a, s,
                                       n, id,
                                       mask ^ (1 << id),
                                       dp));
                }
 
                // Find the cost of current
                // character and move to next
                // position
                else {
                    ans = Math.min(
                        ans,
                        a[prev][id]
                            + solve(
                                  a, s,
                                  n, id,
                                  mask ^ (1 << id),
                                  dp));
                }
            }
        }
 
        // Store the answer for each
        // current state
        dp[mask][prev + 1] = ans;
        return ans;
    }
 
    // Function that returns true
    // if the current bit is set
    public static boolean
    check(int mask, int i)
    {
        int c = (mask & (1 << i));
        return c != 0;
    }
 
    // Function that generates any
    // permutation of the given
    // string with minimum cost
    static void generatePermutation(
        int mask, int n, int a[][],
        String s)
    {
 
        // Initialize dp table
        int dp[][] = new int[(1 << n) + 5][n + 5];
 
        for (int i[] : dp)
            Arrays.fill(i, -1);
 
        // Set all the bits of the
        // current character id
        for (int i = 0;
             i < s.length(); i++) {
 
            int id = s.charAt(i) - 'a';
            mask |= (1 << id);
        }
 
        // Minimum cost of generating
        // the permutation
        System.out.println(solve(
            a, s, n, -1, mask, dp));
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int N = 5;
 
        String str = "abcde";
 
        int mat[][] = { { 0, 5, 1, 5, 3 },
                        { 4, 0, 9, 4, 2 },
                        { 7, 9, 0, 10, 7 },
                        { 1, 2, 8, 0, 2 },
                        { 3, 9, 7, 7, 0 } };
 
        // Function Call
        generatePermutation(0, N, mat, str);
    }
}


Python3
# Python3 program for the
# above approach
 
# Function to find the
# minimum cost to form
# any permutation of
# string s
def solve(a, s, n, prev,
          mask, dp):
    # Base Case
    if (mask == 0):
        return 0;
 
    # Return the precomputed state
    if (dp[mask][prev + 1] != -1):
        return dp[mask][prev + 1];
 
    ans = 10000;
 
    # Iterate over the string and
    # check all possible characters
    # available for current position
    for i in range(len(s)):
        id = ord(s[i]) - ord('a');
 
        # Check if character can be
        # placed at current position
        if (check(mask, id)):
 
            # As there is no previous
            # character so the cost
            # for 1st character is 0
            if (prev == -1):
                ans = min(ans,
                      solve(a, s,
                            n, id,
                            mask ^ (1 <<
                            id), dp));
 
 
            # Find the cost of current
            # character and move to next
            # position
            else:
                ans = min(ans, a[prev][id] +
                      solve(a, s, n,
                            id, mask ^
                            (1 << id), dp));
 
    # Store the answer for each
    # current state
    dp[mask][prev + 1] = ans;
    return ans;
 
 
# Function that returns
# True if the current
# bit is set
def check(mask, i):
   
    c = (mask & (1 << i));
    return c != 0;
 
# Function that generates any
# permutation of the given
# string with minimum cost
def generatePermutation(mask, n,
                        a, s):
 
    # Initialize dp table
    dp = [[-1 for i in range(n + 5)]
              for j in range((1 << n) + 5)]
 
    # Set all the bits of the
    # current character id
    for i in range(len(s)):
        id = ord(s[i]) - ord('a');
        mask |= (1 << id);
 
    # Minimum cost of generating
    # the permutation
    print(solve(a, s, n,
                -1, mask, dp));
 
# Driver Code
if __name__ == '__main__':
   
    N = 5;
    str = "abcde";
    mat = [[0, 5, 1, 5, 3],
           [4, 0, 9, 4, 2],
           [7, 9, 0, 10, 7],
           [1, 2, 8, 0, 2],
           [3, 9, 7, 7, 0]];
 
    # Function Call
    generatePermutation(0, N,
                        mat, str);
 
# This code is contributed by gauravrajput1


C#
// C# program for the
// above approach
using System;
class GFG{
 
// Function to find the minimum cost
// to form any permutation of string s
public static int solve(int[,]a, String s, int n,
                        int prev, int mask, int[,] dp)
{
  // Base Case
  if (mask == 0)
    return 0;
 
  // Return the precomputed state
  if (dp[mask,prev + 1] != -1)
    return dp[mask, prev + 1];
 
  int ans = 10000;
 
  // Iterate over the string and
  // check all possible characters
  // available for current position
  for (int i = 0;
           i < s.Length; i++)
  {
    int id = s[i] - 'a';
 
    // Check if character can be
    // placed at current position
    if (check(mask, id))
    {
      // As there is no previous
      // character so the cost
      // for 1st character is 0
      if (prev == -1)
      {
        ans = Math.Min(ans,
                       solve(a, s, n, id,
                             mask ^ (1 << id), dp));
      }
 
      // Find the cost of current
      // character and move to next
      // position
      else
      {
        ans = Math.Min(ans, a[prev,id] +
                       solve(a, s, n, id,
                             mask ^ (1 << id), dp));
      }
    }
  }
 
  // Store the answer for each
  // current state
  dp[mask, prev + 1] = ans;
  return ans;
}
 
// Function that returns true
// if the current bit is set
public static bool check(int mask, int i)
{
  int c = (mask & (1 << i));
  return c != 0;
}
 
// Function that generates any
// permutation of the given
// string with minimum cost
static void generatePermutation(int mask, int n,
                                int[,]a, String s)
{
  // Initialize dp table
  int [,]dp = new int[(1 << n) + 5,
                      n + 5];
 
  for(int i = 0;
          i < (1 << n) + 5; i++)
    for(int j = 0;
            j < n + 5; j++)
      dp[i, j] = -1;
   
  // Set all the bits of the
  // current character id
  for (int i = 0;
       i < s.Length; i++)
  {
    int id = s[i] - 'a';
    mask |= (1 << id);
  }
 
  // Minimum cost of generating
  // the permutation
  Console.WriteLine(solve(a, s, n,
                          -1, mask, dp));
}
 
// Driver Code
public static void Main(String []args)
{
  int N = 5;
  String str = "abcde";
  int [,]mat = {{0, 5, 1, 5, 3},
                {4, 0, 9, 4, 2},
                {7, 9, 0, 10, 7},
                {1, 2, 8, 0, 2},
                {3, 9, 7, 7, 0}};
 
  // Function Call
  generatePermutation(0, N, mat, str);
}
}
 
// This code is contributed by Rajput-Ji


输出:
8

时间复杂度: O(N * 2 N )
辅助空间: O(N * 2 N )