C++ 中划分为 K 个相等和的子集

c++server side programmingprogramming

假设我们有一个名为 nums 的整数数组和一个正整数 k,检查是否可以将该数组划分为 k 个非空子集,并且这些子集的和都相等。因此,如果数组为 [4,3,2,3,5,2,1] 且 k = 4,则结果为 True,因为给定数组可以分成四个子数组,例如 [[5], [1,4], [2,3], [2,3]],且总和相等。

为了解决这个问题,我们将遵循以下步骤 −

  • 定义两个名为 dp 和 total 的表,大小均为 2^n
  • 对给定数组 nums 进行排序,设置 sum := nums 数组中所有元素的总和
  • 如果 sum mod k 非 0 或 nums 的最后一个元素 > sum / k,则返回 false
  • 设置 dp[0] := true 且 sum := sum / k
  • 对于 i,范围从 0 到 2^n
    • 如果 dp[i] 非零,则
      • 对于 j,范围从 0 到 ,
        • temp := i 或 2 ^ j
        • 如果 temp 与 i 不同,则
          • 如果 nums[j] <= sum – total[i] mod sum,则 dp[temp] := true
          • total[temp] := total[i] + nums[j]
        • 否则,退出循环
  • return dp[(2^n) - 1]

示例(C++)

让我们看下面的实现,以便更好地理解 −

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
   bool canPartitionKSubsets(vector<int>& nums, int k) {
      int n = nums.size();
      vector <bool> dp(1 << n);
      vector <int> total(1 << n);
      sort(nums.begin(), nums.end());
      int sum = 0;
      for(int i = 0; i < nums.size(); i++)sum += nums[i];
      if(sum % k || nums[nums.size() - 1] > sum / k) return false;
      dp[0] = true;
      sum /= k;
      for(int i = 0; i < (1 << n); i++){
         if(dp[i]){
            for(int j = 0; j < n; j++){
               int temp = i | (1 << j);
               if(temp != i){
                  if(nums[j] <= sum - (total[i] % sum)){
                     dp[temp] = true;
                     total[temp] = total[i] + nums[j];
                  }
                  else{
                     break;
                  }
               }
            }
         }
      }
      return dp[(1 << n) - 1];
   }
};
main(){
   Solution ob;
   vector<int> v = {4,3,2,3,5,2,1};
   cout << (ob.canPartitionKSubsets(v, 4));
}

输入

[4,3,2,3,5,2,1]
4

输出

1

相关文章