📜  将数组划分为K个分段,以使各个分段和的按位与最大

📅  最后修改于: 2021-05-06 18:33:20             🧑  作者: Mango

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

例子:

方法:
首先,尝试回答一个更简单的问题:给定一个整数x并确定是否有可能将给定数组划分为K个段,以使段之和按位具有x的所有置位位?
让我们通过第i个段表示元素之和S\textsubscript{i} 。此外,我们姑且称之为段,如果S\textsubscript{i}具有x的所有置位位。现在很清楚的是有一个良好的段,AND( 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<


输出:
41

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