📜  将数字转换为质数段所需的最小拆分

📅  最后修改于: 2021-09-17 06:43:35             🧑  作者: Mango

给定一个字符串s形式的数字,任务是计算和显示所需的最小分割,以便形成的段是 Prime 或打印不可能否则。
例子:

方法:
这个问题是矩阵链乘法的变体,可以使用动态规划解决。
递归地尝试所有可能的拆分,并在每次拆分时检查形成的段是否为素数。考虑一个二维数组dp ,其中dp[i][j]显示从索引 i 到 j 的最小拆分,并返回 dp[0][n] 其中 n 是字符串的长度。
复发:

dp[i][j] = min(1 + solve(i, k) + solve(k + 1, j)) where i <= k <= j

实际上,在上面写的精确循环中,左右段都是非素数,那么1 + INT_MAX + INT_MAX将为负数,从而导致错误答案。
因此,需要对段分开计算。如果发现任何段为非质数,则无需进一步处理。否则返回min(1+left+right)
考虑的基本情况是:

  • 如果数字是质数,则返回 0
  • 如果i==j并且数字是素数,则返回 0
  • 如果i==j并且数字不是素数,则返回 INT_MAX

下面的代码是上述方法的实现:

C++
#include 
using namespace std;
 
int dp[1000][1000] = { 0 };
 
// Checking for prime
bool isprime(long long num)
{
    if (num <= 1)
        return false;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}
// Conversion of string to int
long long convert(string s, int i, int j)
{
    long long temp = 0;
    for (int k = i; k <= j; k++) {
        temp = temp * 10 + (s[k] - '0');
    }
    return temp;
}
// Function to get the minimum splits
int solve(string s, int i, int j)
{
    // Convert the segment to integer or long long
    long long num = convert(s, i, j);
    // Number is prime
    if (isprime(num)) {
        return 0;
    }
    // If a single digit is prime
    if (i == j && isprime(num))
        return 0;
 
    // If single digit is not prime
    if (i == j && isprime(num) == false)
        return INT_MAX;
 
    if (dp[i][j])
        return dp[i][j];
 
    int ans = INT_MAX;
    for (int k = i; k < j; k++) {
        // Recur for left segment
        int left = solve(s, i, k);
        if (left == INT_MAX) {
            continue;
        }
 
        // Recur for right segment
        int right = solve(s, k + 1, j);
        if (right == INT_MAX) {
            continue;
        }
        // Minimum from left and right segment
        ans = min(ans, 1 + left + right);
    }
    return dp[i][j] = ans;
}
int main()
{
 
    string s = "2352";
    int n = s.length();
 
    int cuts = solve(s, 0, n - 1);
    if (cuts != INT_MAX) {
        cout << cuts;
    }
    else {
        cout << "Not Possible";
    }
}


Java
import java.util.*;
 
class GFG
{
 
    static int dp[][] = new int[1000][1000];
 
    // Checking for prime
    static boolean isprime(long num){
        int i;
        if (num <= 1)
            return false;
        for (i = 2; i * i <= num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }
 
    // Conversion of string to int
    static long convert(String s, int i, int j)
    {
        long temp = 0;
        int k;
        for (k = i; k <= j; k++) {
            temp = temp * 10 + (s.charAt(k) - '0');
        }
        return temp;
    }
 
    // Function to get the minimum splits
    static int solve(String s, int i, int j)
    {
        int k;
 
        // Convert the segment to integer or long long
        long num = convert(s, i, j);
 
        // Number is prime
        if (isprime(num)) {
            return 0;
        }
 
        // If a single digit is prime
        if (i == j && isprime(num))
            return 0;
     
        // If single digit is not prime
        if (i == j && isprime(num) == false)
            return Integer.MAX_VALUE;
     
        if (dp[i][j] != 0)
            return dp[i][j];
     
        int ans = Integer.MAX_VALUE;
        for (k = i; k < j; k++) {
 
            // Recur for left segment
            int left = solve(s, i, k);
            if (left == Integer.MAX_VALUE) {
                continue;
            }
     
            // Recur for right segment
            int right = solve(s, k + 1, j);
            if (right == Integer.MAX_VALUE) {
                continue;
            }
 
            // Minimum from left and right segment
            ans = Math.min(ans, 1 + left + right);
        }
        return dp[i][j] = ans;
    }
     
    public static void main (String []args)
    {
     
        String s = "2352";
        int n = s.length();
     
        int cuts = solve(s, 0, n - 1);
        if (cuts != Integer.MAX_VALUE) {
            System.out.print(cuts);
        }
        else {
            System.out.print("Not Possible");
        }
    }
}
 
// This code is contributed by chitranayal


Python3
# Python3 Implementation of the above approach
import numpy as np;
import sys
 
dp = np.zeros((1000,1000)) ;
 
INT_MAX = sys.maxsize;
 
# Checking for prime
def isprime(num) :
 
    if (num <= 1) :
        return False;
    for i in range(2, int(num ** (1/2)) + 1) :
        if (num % i == 0) :
            return False;
    return True;
 
# Conversion of string to int
def convert(s, i, j) :
 
    temp = 0;
    for k in range(i, j + 1) :
        temp = temp * 10 + (ord(s[k]) - ord('0'));
 
    return temp;
 
# Function to get the minimum splits
def solve(s, i, j) :
 
    # Convert the segment to integer or long long
    num = convert(s, i, j);
    # Number is prime
    if (isprime(num)) :
        return 0;
 
    # If a single digit is prime
    if (i == j and isprime(num)) :
        return 0;
 
    # If single digit is not prime
    if (i == j and isprime(num) == False) :
        return INT_MAX;
 
    if (dp[i][j]) :
        return dp[i][j];
 
    ans = INT_MAX;
     
    for k in range(i, j) :
        # Recur for left segment
        left = solve(s, i, k);
        if (left == INT_MAX) :
            continue;
 
        # Recur for right segment
        right = solve(s, k + 1, j);
        if (right == INT_MAX) :
            continue;
     
        # Minimum from left and right segment
        ans = min(ans, 1 + left + right);
     
    dp[i][j] = ans;
     
    return ans;
 
# Driver code   
if __name__ == "__main__" :
 
    s = "2352";
    n = len(s);
 
    cuts = solve(s, 0, n - 1);
    if (cuts != INT_MAX) :
        print(cuts);
     
    else :
        print("Not Possible");
 
# This code is converted by Yash_R


C#
using System;
 
class GFG
{
  
    static int [,]dp = new int[1000,1000];
  
    // Checking for prime
    static bool isprime(long num){
        int i;
        if (num <= 1)
            return false;
        for (i = 2; i * i <= num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }
  
    // Conversion of string to int
    static long convert(String s, int i, int j)
    {
        long temp = 0;
        int k;
        for (k = i; k <= j; k++) {
            temp = temp * 10 + (s[k] - '0');
        }
        return temp;
    }
  
    // Function to get the minimum splits
    static int solve(String s, int i, int j)
    {
        int k;
  
        // Convert the segment to integer or long long
        long num = convert(s, i, j);
  
        // Number is prime
        if (isprime(num)) {
            return 0;
        }
  
        // If a single digit is prime
        if (i == j && isprime(num))
            return 0;
      
        // If single digit is not prime
        if (i == j && isprime(num) == false)
            return int.MaxValue;
      
        if (dp[i,j] != 0)
            return dp[i, j];
      
        int ans = int.MaxValue;
        for (k = i; k < j; k++) {
  
            // Recur for left segment
            int left = solve(s, i, k);
            if (left == int.MaxValue) {
                continue;
            }
      
            // Recur for right segment
            int right = solve(s, k + 1, j);
            if (right == int.MaxValue) {
                continue;
            }
  
            // Minimum from left and right segment
            ans = Math.Min(ans, 1 + left + right);
        }
        return dp[i,j] = ans;
    }
      
    public static void Main(String []args)
    {
      
        String s = "2352";
        int n = s.Length;
      
        int cuts = solve(s, 0, n - 1);
        if (cuts != int.MaxValue) {
            Console.Write(cuts);
        }
        else {
            Console.Write("Not Possible");
        }
    }
}
 
// This code is contributed by PrinciRaj1992


Javascript


输出:
2