给定大小为N * M的矩阵mat [] [] ,任务是找到使给定矩阵至少一行的所有元素为素数所需的最小操作数。在每个操作中,根据以下条件合并矩阵的任意两行:
- 如果矩阵两行的第k个元素(即mat [i] [k]和mat [j] [k]是素数或复合数),则合并行的第k个元素包含min(mat [i] [ k],mat [j] [k]) 。
- 否则,合并行的第k个元素包含素数元素。
如果不可能将一行的所有元素都作为质数,则打印-1 。
例子:
Input: mat[][] = { { 4, 6, 5 }, { 2, 9, 12 }, { 32, 7, 18 }, { 12, 4, 35 } }
Output: 2
Explanation:
Merging mat[0] and mat[1] modifies mat[][] to { { 2, 6, 5 }, { 32, 7, 18 }, { 12, 4, 35 } }
Merging mat[0] and mat[1] modifies mat[][] to { { 2, 7, 5 }, { 12, 4, 35 } }
Since first row of the matrix consists only of prime numbers, the required output is 2.
Input: mat[][] = { {4, 6}, {8, 3} }
Output: -1
Explanation:
Merging mat[0] and mat[1] modifies mat[][] to { { 4, 3 } }
Since none of the elements in the row is prime, the required output is -1.
方法:使用带位掩码的动态编程可以解决该问题。请按照以下步骤解决问题:
- 初始化变量,例如bitmask ,如果行的第i列不是素数,则将bitmask的第i位存储在其中。
- 初始化一个数组,例如dp [] ,其中dp [X]存储在一行中获取X个质数的计数所需的最小操作数。
- 遍历矩阵的每一行,并更新每一行的位掩码值。使用变量j迭代[[1 <<(M – 1)),0]范围,并更新dp [j |位掩码]到min(dp [j |位掩码],dp [j] + 1) 。
- 最后,检查连续获取M个质数所需的最小操作数是否大于N ,即,检查dp [(1 <<(M – 1))]是否大于N。如果发现是真的,则打印-1 。
- 否则,打印(dp [(1 <<(M – 1))] – 1)的值。
下面是上述方法的实现。
Java
// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to generate all prime
// numbers using Sieve of Eratosthenes
private static boolean[] prime;
// Function to check if a number
// is prime or not
private static void sieve(int n)
{
// prime[i]: Check if i is a
// prime number or not
prime = new boolean[n + 1];
// Initialize prime[]
// array to true
Arrays.fill(prime, true);
// Iterate over the range
// [2, sqrt(n)]
for (int p = 2; p * p <= n;
p++) {
// If p is a prime number
if (prime[p] == true) {
// Mark all multiples
// of i to false
for (int i = p * p;
i <= n; i += p)
// Update i
prime[i] = false;
}
}
}
// Function to find minimum operations
// to make all elements of at least one
// row of the matrix as prime numbers
private static int MinWays(int[][] a,
int n, int m)
{
// dp[i]: Stores minimum operations
// to get i prime numbers in a row
int[] dp = new int[1 << m];
// Initialize dp[] array
// to (n + 1)
Arrays.fill(dp, n + 1);
// Traverse the array
for (int i = 0; i < a.length;
i++) {
// Stores count of prime
// numbers in a i-th row
int bitmask = BitMask(a[i]);
// Iterate over the range
// [(1 << m) - 1, 0]
for (int j = (1 << m) - 1;
j >= 0; j--) {
// If a row exist which
// contains j prime numbers
if (dp[j] != n + 1) {
// Update dp[j | bitmask]
dp[j | bitmask]
= Math.min(dp[j | bitmask],
dp[j] + 1);
}
}
// Update dp[bitmask]
dp[bitmask] = 1;
}
// Return minimum operations to get a row
// of the matrix with all prime numbers
return (dp[(1 << m) - 1] - 1) == (n + 1)
? -1
: (dp[(1 << m) - 1] - 1);
}
// Function to count prime
// numbers in a row
private static int BitMask(int[] a)
{
// i-th bit of bitmask check if
// i-th column is a prime or not
int bitmask = 0;
// Travere the array
for (int i = 0; i < a.length;
i++) {
// if a[i] is a prime number
if (prime[a[i]]) {
// Update bitmask
bitmask |= (1 << i);
}
}
return bitmask;
}
// Driver Code
public static void main(String[] args)
{
int[][] mat = { { 4, 6, 5, 8 },
{ 2, 9, 12, 14 },
{ 32, 7, 18, 16 },
{ 12, 4, 35, 17 } };
// Stores count of columns
// in the matrix
int m = mat[0].length;
// Stores length
int n = mat.length;
// Calulate all prime numbers in
// range [1, max] using sieve
int max = 10000;
sieve(max);
// Function Call
System.out.println(
MinWays(mat, n, m));
}
}
Python3
# Python 3 program to implement
# the above approach
from math import sqrt
# Function to generate all prime
# numbers using Sieve of Eratosthenes
prime = [True for i in range(10001)]
# Function to check if a number
# is prime or not
def sieve(n):
# prime[i]: Check if i is a
# prime number or not
global prime
# Iterate over the range
# [2, sqrt(n)]
for p in range(2,int(sqrt(10000)) + 1, 1):
# If p is a prime number
if (prime[p] == True):
# Mark all multiples
# of i to false
for i in range(p * p, 10001, p):
# Update i
prime[i] = False
# Function to find minimum operations
# to make all elements of at least one
# row of the matrix as prime numbers
def MinWays(a, n, m):
# dp[i]: Stores minimum operations
# to get i prime numbers in a row
dp = [n + 1 for i in range(1 << m)]
# Traverse the array
for i in range(len(a)):
# Stores count of prime
# numbers in a i-th row
bitmask = BitMask(a[i])
# Iterate over the range
# [(1 << m) - 1, 0]
j = (1 << m) - 1
while(j >= 0):
# If a row exist which
# contains j prime numbers
if (dp[j] != n + 1):
# Update dp[j | bitmask]
dp[j | bitmask] = min(dp[j | bitmask],dp[j] + 1)
j -= 1
# Update dp[bitmask]
dp[bitmask] = 1
# Return minimum operations to get a row
# of the matrix with all prime numbers
if (dp[(1 << m) - 1] - 1) == (n + 1):
return -1
else:
return (dp[(1 << m) - 1] - 1)
# Function to count prime
# numbers in a row
def BitMask(a):
global prime
# i-th bit of bitmask check if
# i-th column is a prime or not
bitmask = 0
# Travere the array
for i in range(len(a)):
# if a[i] is a prime number
if (prime[a[i]]):
# Update bitmask
bitmask |= (1 << i)
return bitmask
# Driver Code
if __name__ == '__main__':
mat = [[4, 6, 5, 8],
[2, 9, 12, 14],
[32, 7, 18, 16],
[12, 4, 35, 17]]
# Stores count of columns
# in the matrix
m = len(mat[0])
# Stores length
n = len(mat)
# Calulate all prime numbers in
# range [1, max] using sieve
max = 10000
sieve(max)
# Function Call
print(MinWays(mat, n, m))
# Thhis code is contributed by SURENDRA_GANGWAR.
C#
// C# program to implement
// the above approach
using System;
public class GFG
{
// Function to generate all prime
// numbers using Sieve of Eratosthenes
private static bool[] prime;
// Function to check if a number
// is prime or not
private static void sieve(int n)
{
// prime[i]: Check if i is a
// prime number or not
prime = new bool[n + 1];
// Initialize prime[]
// array to true
for (int i = 0; i < prime.Length; i++)
prime[i] = true;
// Iterate over the range
// [2, sqrt(n)]
for (int p = 2; p * p <= n;
p++) {
// If p is a prime number
if (prime[p] == true)
{
// Mark all multiples
// of i to false
for (int i = p * p;
i <= n; i += p)
// Update i
prime[i] = false;
}
}
}
// Function to find minimum operations
// to make all elements of at least one
// row of the matrix as prime numbers
private static int MinWays(int[,] a,
int n, int m)
{
// dp[i]: Stores minimum operations
// to get i prime numbers in a row
int[] dp = new int[1 << m];
// Initialize []dp array
// to (n + 1)
for (int i = 0; i < dp.Length;i++)
{
dp[i] = n + 1;
}
// Traverse the array
for (int i = 0; i < a.GetLength(0);
i++)
{
// Stores count of prime
// numbers in a i-th row
int bitmask = BitMask(GetRow(a,i));
// Iterate over the range
// [(1 << m) - 1, 0]
for (int j = (1 << m) - 1;
j >= 0; j--)
{
// If a row exist which
// contains j prime numbers
if (dp[j] != n + 1)
{
// Update dp[j | bitmask]
dp[j | bitmask]
= Math.Min(dp[j | bitmask],
dp[j] + 1);
}
}
// Update dp[bitmask]
dp[bitmask] = 1;
}
// Return minimum operations to get a row
// of the matrix with all prime numbers
return (dp[(1 << m) - 1] - 1) == (n + 1)
? -1
: (dp[(1 << m) - 1] - 1);
}
// Function to count prime
// numbers in a row
private static int BitMask(int[] a)
{
// i-th bit of bitmask check if
// i-th column is a prime or not
int bitmask = 0;
// Travere the array
for (int i = 0; i < a.Length;
i++) {
// if a[i] is a prime number
if (prime[a[i]])
{
// Update bitmask
bitmask |= (1 << i);
}
}
return bitmask;
}
public static int[] GetRow(int[,] matrix, int row)
{
var rowLength = matrix.GetLength(1);
var rowVector = new int[rowLength];
for (var i = 0; i < rowLength; i++)
rowVector[i] = matrix[row, i];
return rowVector;
}
// Driver Code
public static void Main(String[] args)
{
int[,] mat = { { 4, 6, 5, 8 },
{ 2, 9, 12, 14 },
{ 32, 7, 18, 16 },
{ 12, 4, 35, 17 } };
// Stores count of columns
// in the matrix
int m = mat.GetLength(0);
// Stores length
int n = mat.GetLength(1);
// Calulate all prime numbers in
// range [1, max] using sieve
int max = 10000;
sieve(max);
// Function Call
Console.WriteLine(
MinWays(mat, n, m));
}
}
// This code is contributed by shikhasingrajput
3
时间复杂度: O(X * log(log(X))+ N * M * 2 M ),其中X是矩阵的最大元素
辅助空间: O(X + 2 M )