📌  相关文章
📜  将数组划分为 K 个段,使得单个段总和的按位 AND 最大化

📅  最后修改于: 2021-09-22 10:08:03             🧑  作者: Mango

给定一个大小为N的数组和一个整数K 。任务是将数组划分为K 个段,使得单个段总和的按位AND最大化。找出可以得到的按位的最大值。

例子:

方法:
首先,尝试回答一个更简单的问题:给定一个整数x并确定是否可以将给定数组划分为K 个段,使得段总和的按位AND具有x 的所有设置位?
让我们将第 i段中元素的总和表示为S\textsubscript{i}  .另外,让我们称一个段为好,如果S\textsubscript{i}  具有x 的所有设置位。现在很清楚,对于一个好的段iAND ( S\textsubscript{i}  , x )= x
此外,所有K段都应该有利于获得x 的按位与。现在检查我们是否可以将数组划分为k 个好的段。我们可以在这里使用动态规划。
dp[i][j]= true ,表示可以将前i 个元素划分为j 个段,使得所有j都是好的段,否则为false
以上 dp 的循环是:

贪婪地从可能答案的最高位开始构建dp表。
下面是上述方法的实现:

C++
// CPP program to find maximum possible AND
#include 
using namespace std;
 
// Function to check whether a k segment partition
// is possible such that bitwise AND is 'mask'
bool checkpossible(int mask, int* arr, int* prefix, int n,
                                                  int k)
{
    // dp[i][j] stores whether it is possible to partition
    // first i elements into j segments such that all j
    // segments are 'good'
    bool dp[n + 1][k + 1];
 
    // Initialising dp
    memset(dp, 0, sizeof(dp));
    dp[0][0] = 1;
 
    // Filling dp in bottom-up manner
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= k; j++) {
            // Finding a cut such that first l elements
            // can be partitioned into j-1 'good' segments
            // and arr[l+1]+...+arr[i] is a 'good' segment
            for (int l = i - 1; l >= 0; --l) {
                if (dp[l][j - 1] && (((prefix[i] - prefix[l])
                           & mask) == mask)) {
                    dp[i][j] = 1;
                    break;
                }
            }
        }
    }
 
    return dp[n][k];
}
 
// Function to find maximum possible AND
int Partition(int arr[], int n, int k)
{
    // Array to store prfix sums
    int prefix[n+1];
 
    for (int i = 1; i <= n; i++) {
        prefix[i] = prefix[i - 1] + arr[i];
    }
 
    // Maximum no of bits in the possible answer
    int LOGS = 20;
 
    // This will store the final answer
    int ans = 0;
 
    // Constructing answer greedily selecting
    // from the higher most bit
    for (int i = LOGS; i >= 0; --i) {
        // Checking if array can be partitioned
        // such that the bitwise AND is ans|(1<


Java
// Java program to find maximum possible AND
 
class GFG
{
     
    // Function to check whether a k segment partition
    // is possible such that bitwise AND is 'mask'
    static boolean checkpossible(int mask, int arr[],
                                int prefix[], int n, int k)
    {
        int i,j;
         
        // dp[i][j] stores whether it is possible to partition
        // first i elements into j segments such that all j
        // segments are 'good'
        boolean dp[][] = new boolean[n + 1][k + 1];
     
        // Initialising dp
        for(i = 0; i < n + 1; i++)
        {
            for(j = 0; j < k + 1; j++)
            {
                dp[i][j] = false ;
            }
        }
         
        dp[0][0] = true;
     
        // Filling dp in bottom-up manner
        for ( i = 1; i <= n; i++)
        {
            for (j = 1; j <= k; j++)
            {
                // Finding a cut such that first l elements
                // can be partitioned into j-1 'good' segments
                // and arr[l+1]+...+arr[i] is a 'good' segment
                for (int l = i - 1; l >= 0; --l)
                {
                    if (dp[l][j - 1] && (((prefix[i] - prefix[l])
                            & mask) == mask))
                    {
                        dp[i][j] = true;
                        break;
                    }
                }
            }
        }
     
        return dp[n][k];
    }
     
    // Function to find maximum possible AND
    static int Partition(int arr[], int n, int k)
    {
        // Array to store prfix sums
        int prefix[] = new int[n+1];
     
        for (int i = 1; i <= n; i++)
        {
            prefix[i] = prefix[i - 1] + arr[i];
        }
     
        // Maximum no of bits in the possible answer
        int LOGS = 20;
     
        // This will store the final answer
        int ans = 0;
     
        // Constructing answer greedily selecting
        // from the higher most bit
        for (int i = LOGS; i >= 0; --i)
        {
            // Checking if array can be partitioned
            // such that the bitwise AND is ans|(1<


Python3
# Python3 program to find maximum possible AND
 
# Function to check whether a k segment partition
# is possible such that bitwise AND is 'mask'
def checkpossible(mask,arr,prefix, n,k):
     
    # dp[i][j] stores whether it is possible to partition
    # first i elements into j segments such that all j
    # segments are 'good'
    dp=[[0 for i in range(k+1)] for i in range(n + 1)]
 
    # Initialising dp
    dp[0][0] = 1
 
    # Filling dp in bottom-up manner
    for i in range(1, n+1):
        for j in range(1, k+1):
             
            # Finding a cut such that first l elements
            # can be partitioned into j-1 'good' segments
            # and arr[l+1]+...+arr[i] is a 'good' segment
            for l in range(i-1,-1,-1):
                if (dp[l][j - 1] and (((prefix[i] - prefix[l]) & mask) == mask)):
                    dp[i][j] = 1
                    break
 
    return dp[n][k]
 
 
# Function to find maximum possible AND
def Partition(arr, n, k):
    # Array to store prfix sums
    prefix=[0 for i in range(n+1)]
 
    for i in range(1,n+1):
        prefix[i] = prefix[i - 1] + arr[i]
 
    # Maximum no of bits in the possible answer
    LOGS = 20
 
    # This will store the final answer
    ans = 0
 
    # Constructing answer greedily selecting
    # from the higher most bit
    for i in range(LOGS,-1,-1):
        # Checking if array can be partitioned
        # such that the bitwise AND is ans|(1<


C#
// C# program to find maximum possible AND
using System;
     
class GFG
{
     
    // Function to check whether a
    // k-segment partition is possible
    // such that bitwise AND is 'mask'
    static Boolean checkpossible(int mask, int []arr,
                                 int []prefix,
                                 int n, int k)
    {
        int i, j;
         
        // dp[i,j] stores whether it is possible
        // to partition first i elements into
        // j-segments such that all j-segments are 'good'
        Boolean[,] dp = new Boolean[n + 1, k + 1];
     
        // Initialising dp
        for(i = 0; i < n + 1; i++)
        {
            for(j = 0; j < k + 1; j++)
            {
                dp[i, j] = false;
            }
        }
         
        dp[0, 0] = true;
     
        // Filling dp in bottom-up manner
        for ( i = 1; i <= n; i++)
        {
            for (j = 1; j <= k; j++)
            {
                // Finding a cut such that first l elements
                // can be partitioned into j-1 'good' segments
                // and arr[l+1]+...+arr[i] is a 'good' segment
                for (int l = i - 1; l >= 0; --l)
                {
                    if (dp[l, j - 1] &&
                     (((prefix[i] - prefix[l]) &
                        mask) == mask))
                    {
                        dp[i, j] = true;
                        break;
                    }
                }
            }
        }
        return dp[n, k];
    }
     
    // Function to find maximum possible AND
    static int Partition(int []arr, int n, int k)
    {
        // Array to store prfix sums
        int []prefix = new int[n + 1];
     
        for (int i = 1; i <= n; i++)
        {
            prefix[i] = prefix[i - 1] + arr[i];
        }
     
        // Maximum no of bits in the possible answer
        int LOGS = 20;
     
        // This will store the final answer
        int ans = 0;
     
        // Constructing answer greedily selecting
        // from the higher most bit
        for (int i = LOGS; i >= 0; --i)
        {
            // Checking if array can be partitioned
            // such that the bitwise AND is ans|(1<


Javascript


输出:
41

时间复杂度: O( n^2  klog(S)),其中 S = S\textsubscript{1}  + S\textsubscript{2}  +….+ S\textsubscript{k}  .

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程