C++でのK個の等和サブセットへの分割
numsと呼ばれる整数の配列と正の整数kがあるとします。この配列を、合計がすべて同じであるk個の空でないサブセットに分割できるかどうかを確認します。したがって、配列が[4,3,2,3,5,2,1]のようで、k =4の場合、指定された配列は[[5]、[ 1,4]、[2,3]、[2,3]]の合計は等しい。
これを解決するには、次の手順に従います-
- dpと呼ばれる2つのテーブルと合計サイズ2^nを定義します。
- 指定された配列numsを並べ替え、sum:=nums配列内のすべての要素の合計を設定します
- summodkが0以外またはnumsの最後の要素>sum/ kの場合、falseを返します
- set dp [0]:=true and sum:=sum / k
- 0〜2^nの範囲のiの場合
- dp [i]がゼロ以外の場合、
- 0〜の範囲のjの場合、
- temp:=i OR 2 ^ j
- tempがiと同じでない場合、
- nums [j] <=sum – total [i] mod sumの場合、dp [temp]:=true
- total [temp]:=total [i] + nums [j]
- それ以外の場合はループから出てきます
- 0〜の範囲のjの場合、
- dp [i]がゼロ以外の場合、
- return dp [(2 ^ n)-1]
理解を深めるために、次の実装を見てみましょう-
#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
-
C++でセットをk個のサブセットに分割する方法の数を数えます
与えられた2つの数字eとp。目標は、セットのe個の要素をp個のパーティション/サブセットに分割できる方法の数を数えることです。 例 入力 e=4 p=2 出力 Count of number of ways to partition a set into k subsets are: 7 説明 If elements are: a b c d then ways to divide them into 2 partitions are: (a,b,c)−(d), (a,b)−(c,d), (a,b,c)−(d), (a)−(b,c,d), (
-
C++での等しいツリーパーティション
n個のノードを持つ二分木があるとすると、元のツリーの1つのエッジを削除した後、値の合計が等しい2つのツリーにツリーを分割できるかどうかを確認するタスクがあります。 したがって、入力が次のような場合 そうすれば、出力は真になります。 これを解決するには、次の手順に従います- 1つのスタックstを定義する 関数solve()を定義します。これはノードを取ります ノードがnullの場合、- 0を返す leftSum:=solve(ノードの左側) rightSum:=solve(ノードの権利) curr:=val + leftSum+rig