给定一个大小为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列是素数,则位掩码的第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;
// Calculate 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)
# Calculate 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);
// Calculate 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 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。