给定两个大小为N 的数组A[]和B[] ,任务是找到数组A[]和B[]中相同索引元素的按位与的最大和,可以通过重新排列获得 数组B[]以任何顺序。
例子:
Input: A[] = {1, 2, 3, 4}, B[] = {3, 4, 1, 2}
Output: 10
Explanation: One possible way is to obtain the maximum value is to rearrange the array B[] to {1, 2, 3, 4}.
Therefore, sum of Bitwise AND of same-indexed elements of the arrays A[] and B[] = { 1&1 + 2&2 + 3&3 + 4&4 = 10), which is the maximum possible.
Input: A[] = {3, 5, 7, 11}, B[] = {2, 6, 10, 12}
Output: 22
朴素的方法:解决问题的最简单的方法是生成数组B[] 的所有可能排列,并为每个排列计算数组A[]和B[]中相同索引元素的按位与的总和并更新最大值可能的总和。最后,打印可能的最大和。
时间复杂度: O(N! * N)
辅助空间: O(1)
高效的方法:上述方法也可以基于以下观察进行优化:
- For each array element of A[] the idea is to chose a not selected array element of B[] using bitmasking which will give maximum bitwise AND sum upto the current index.
- The idea is to use Dynamic Programming with bitmasking as it has overlapping subproblems and optimal substructure.
- Suppose, dp(i, mask) represents the maximum bitwise AND sum of array A[] and i, with the selected elements of array B[] represented by bits-position of mask.
- Then the transition from one state to another state can be defined as:
- For all j in the range [0, N]:
- If the jth bit of mask is not set then, dp(i, mask) = max(dp(i, mask|(1<
- If the jth bit of mask is not set then, dp(i, mask) = max(dp(i, mask|(1<
- For all j in the range [0, N]:
请按照以下步骤解决问题:
- 定义一个向量向量表示维度为N*2 N 的dp ,值为-1以存储所有 dp 状态。
- 定义一个递归的 Dp函数,比如maximizeAndUtil(i, mask)来找到两个数组A[]和B[]中相同位置的元素的按位与的最大和:
- 基本情况,如果i等于N则返回0 。
- 如果dp[i][mask]不等于-1,即已经访问过,则返回dp[i][mask]。
- 使用变量j在范围[0, N-1] 上迭代,并且在每次迭代中,如果掩码中的第j位未设置,则将dp[i][mask]更新为dp[i][mask] = max(dp[ i][掩码], maximizeUtil(i+1, mask| 2 j )。
- 最后,返回dp[i][mask]。
- 调用递归函数maximumAnd(0, 0)并打印它返回的值作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to implement recursive DP
int maximizeAnd(int i, int mask,
int* A, int* B, int N,
vector >& dp)
{
// If i is equal to N
if (i == N)
return 0;
// If dp[i][mask] is not
// equal to -1
if (dp[i][mask] != -1)
return dp[i][mask];
// Iterate over the array B[]
for (int j = 0; j < N; ++j) {
// If current element
// is not yet selected
if (!(mask & (1 << j))) {
// Update dp[i][mask]
dp[i][mask] = max(
dp[i][mask],
(A[i] & B[j])
+ maximizeAnd(i + 1, mask | (1 << j), A,
B, N, dp));
}
}
// Return dp[i][mask]
return dp[i][mask];
}
// Function to obtain maximum sum
// of Bitwise AND of same-indexed
// elements from the arrays A[] and B[]
int maximizeAndUtil(int* A, int* B, int N)
{
// Stores all dp-states
vector > dp(
N, vector(1 << N + 1, -1));
// Returns the maximum value
// returned by the function maximizeAnd()
return maximizeAnd(0, 0, A, B, N, dp);
}
// Driver Code
int main()
{
int A[] = { 3, 5, 7, 11 };
int B[] = { 2, 6, 10, 12 };
int N = sizeof A / sizeof A[0];
cout << maximizeAndUtil(A, B, N);
}
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
// Function to implement recursive DP
static int maximizeAnd(int i, int mask, int A[],
int B[], int N, int[][] dp)
{
// If i is equal to N
if (i == N)
return 0;
// If dp[i][mask] is not
// equal to -1
if (dp[i][mask] != -1)
return dp[i][mask];
// Iterate over the array B[]
for (int j = 0; j < N; ++j) {
// If current element
// is not yet selected
if ((mask & (1 << j)) == 0) {
// Update dp[i][mask]
dp[i][mask] = Math.max(
dp[i][mask],
(A[i] & B[j])
+ maximizeAnd(i + 1,
mask | (1 << j), A, B,
N, dp));
}
}
// Return dp[i][mask]
return dp[i][mask];
}
// Function to obtain maximum sum
// of Bitwise AND of same-indexed
// elements from the arrays A[] and B[]
static int maximizeAndUtil(int A[], int B[], int N)
{
// Stores all dp-states
int dp[][] = new int[N][(1 << N) + 1];
for (int dd[] : dp)
Arrays.fill(dd, -1);
// Returns the maximum value
// returned by the function maximizeAnd()
return maximizeAnd(0, 0, A, B, N, dp);
}
// Driver Code
public static void main(String[] args)
{
int A[] = { 3, 5, 7, 11 };
int B[] = { 2, 6, 10, 12 };
int N = A.length;
System.out.print(maximizeAndUtil(A, B, N));
}
}
// This code is contributed by Kingash.
Python3
# Python3 program for the above approach
# Function to implement recursive DP
def maximizeAnd(i, mask, A, B, N, dp):
# If i is equal to N
if (i == N):
return 0
# If dp[i][mask] is not
# equal to -1
if (dp[i][mask] != -1):
return dp[i][mask]
# Iterate over the array B[]
for j in range(N):
# If current element
# is not yet selected
if ((mask & (1 << j)) == 0):
# Update dp[i][mask]
dp[i][mask] = max(
dp[i][mask],(A[i] & B[j]) +
maximizeAnd(i + 1, mask | (1 << j),
A, B, N, dp))
# Return dp[i][mask]
return dp[i][mask]
# Function to obtain maximum sum
# of Bitwise AND of same-indexed
# elements from the arrays A[] and B[]
def maximizeAndUtil(A, B, N):
# Stores all dp-states
temp = [-1 for i in range(1 << N + 1)]
dp = [temp for i in range(N)]
# Returns the maximum value
# returned by the function maximizeAnd()
return maximizeAnd(0, 0, A, B, N, dp)
# Driver Code
if __name__ == '__main__':
A = [ 3, 5, 7, 11 ]
B = [ 2, 6, 10, 12 ]
N = len(A)
print(maximizeAndUtil(A, B, N))
# This code is contributed by ipg2016107
C#
// C# program for the above approach
using System;
class GFG {
// Function to implement recursive DP
static int maximizeAnd(int i, int mask, int[] A,
int[] B, int N, int[,] dp)
{
// If i is equal to N
if (i == N)
return 0;
// If dp[i][mask] is not
// equal to -1
if (dp[i, mask] != -1)
return dp[i, mask];
// Iterate over the array B[]
for (int j = 0; j < N; ++j) {
// If current element
// is not yet selected
if ((mask & (1 << j)) == 0) {
// Update dp[i][mask]
dp[i, mask] = Math.Max(
dp[i, mask],
(A[i] & B[j])
+ maximizeAnd(i + 1,
mask | (1 << j), A, B,
N, dp));
}
}
// Return dp[i][mask]
return dp[i, mask];
}
// Function to obtain maximum sum
// of Bitwise AND of same-indexed
// elements from the arrays A[] and B[]
static int maximizeAndUtil(int[] A, int[] B, int N)
{
// Stores all dp-states
int[,] dp = new int[N, (1 << N) + 1];
for(int i = 0; i
Javascript
22
时间复杂度: O (N 2 * 2 N)
辅助空间: O(N * 2 N )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。