Algorithm 将集合划分为等和的K个子集
我正在做一个练习,把一个集合分成K个等和的子集。 比方说Algorithm 将集合划分为等和的K个子集,algorithm,recursion,data-structures,backtracking,subset-sum,Algorithm,Recursion,Data Structures,Backtracking,Subset Sum,我正在做一个练习,把一个集合分成K个等和的子集。 比方说 Input : arr = [2, 1, 4, 5, 6], K = 3 Output : Yes we can divide above array into 3 parts with equal sum as [[2, 4], [1, 5], [6]] 我在这里找到了解决办法, //C++程序检查数组是否可以 //划分为等和的K个子集 #包括 使用名称空间std; //检验K等和的递归实用方法 //数组的子竞争 /** 数组-给
Input : arr = [2, 1, 4, 5, 6], K = 3
Output : Yes
we can divide above array into 3 parts with equal
sum as [[2, 4], [1, 5], [6]]
我在这里找到了解决办法,
<代码> //C++程序检查数组是否可以
//划分为等和的K个子集
#包括
使用名称空间std;
//检验K等和的递归实用方法
//数组的子竞争
/**
数组-给定的输入数组
subsetSum array—用于存储数组的每个子集的总和
take-boolean数组检查元素
是否考虑和划分
K-需要的分区数
N-数组中元素的总数
curIdx-当前子板块指数
limitIdx-数组元素应位于的位置的lastIdx
上当*/
bool isKPartitionPossibleRec(内部arr[],内部子项目[],bool Take[],
整数子集,整数K,整数N,整数curIdx,整数limitIdx)
{
if(subsetSum[curIdx]==子集)
{
/*当前索引(K-2)表示相等的(K-1)子集
sum last partition已保留sum“subset”*/
if(curIdx==K-2)
返回true;
//对下一个子集的递归调用
返回isKPartitionPossibleRec(arr、子项、已取、子项、,
K、 N,curIdx+1,N-1);
}
//从limitIdx开始,将元素包含到当前分区中
对于(int i=limitIdx;i>=0;i--)
{
//如果已拍摄,请继续
如果(采取[i])
继续;
int tmp=子系统[curIdx]+arr[i];
//如果temp小于subset,则仅包含元素
//并递归调用
如果(tmp你确实意识到这个问题是NP难的。在动态规划中,划分为2有一个简单的伪多项式时间算法,但显然,因为对于k=2,一般情况下是NP难的,所以这个问题也是。我的问题是,当数组是
4,4,1,3,2,3,2,1
时,该算法试图通过添加ng1+2+2
然后,3+3
或3+1
等等。它没有得到分区,最后将其解为[[4,1],[4,1],[3,2],[3,2]]。我不确定该算法如何找到替代方案?什么是“没有得到分区”意思是?@j_random_hacker我的意思是当数组4,4,1,3,2,2,1
时,它尝试[[2,2,1][4,1]],这不是等和的K次分区。我还是不太明白你的意思…是[[2,2,1],[4,1]]它的第一次尝试?毫不奇怪,这第一次尝试不是一个有效的解决方案;像这样的回溯算法的整个设计是不断尝试解决方案,直到找到一个有效的解决方案。这可能需要很长时间。你知道这个问题是NP难的。划分为2在动态p中有一个简单的伪多项式时间算法程序设计没有考虑k。但是很明显,因为对于k=2,一般情况是np难的,所以这个问题也是。我的问题是,当数组是4,4,1,3,2,3,2,1
时,算法试图通过添加1+2+2
然后,3+3
或3+1
等等来解决它。它没有得到分区,最后是我不知道这个算法是如何找到替代方案的?什么是“没有得到分区”的意思?@j_random_hacker我的意思是当数组4,4,1,3,2,2,1
,它尝试[[2,2,1][4,1]],这不是等和的K次分区。我还是不明白你的意思…是什么[[2,2,1],[4,1]]它的第一次尝试?毫不奇怪,这第一次尝试不是一个有效的解决方案;像这样的回溯算法的整个设计是不断尝试解决方案,直到找到一个有效的解决方案。这可能需要很长时间。
// C++ program to check whether an array can be
// partitioned into K subsets of equal sum
#include <bits/stdc++.h>
using namespace std;
// Recursive Utility method to check K equal sum
// subsetition of array
/**
array - given input array
subsetSum array - sum to store each subset of the array
taken - boolean array to check whether element
is taken into sum partition or not
K - number of partitions needed
N - total number of element in array
curIdx - current subsetSum index
limitIdx - lastIdx from where array element should
be taken */
bool isKPartitionPossibleRec(int arr[], int subsetSum[], bool taken[],
int subset, int K, int N, int curIdx, int limitIdx)
{
if (subsetSum[curIdx] == subset)
{
/* current index (K - 2) represents (K - 1) subsets of equal
sum last partition will already remain with sum 'subset'*/
if (curIdx == K - 2)
return true;
// recursive call for next subsetition
return isKPartitionPossibleRec(arr, subsetSum, taken, subset,
K, N, curIdx + 1, N - 1);
}
// start from limitIdx and include elements into current partition
for (int i = limitIdx; i >= 0; i--)
{
// if already taken, continue
if (taken[i])
continue;
int tmp = subsetSum[curIdx] + arr[i];
// if temp is less than subset then only include the element
// and call recursively
if (tmp <= subset)
{
// mark the element and include into current partition sum
taken[i] = true;
subsetSum[curIdx] += arr[i];
bool nxt = isKPartitionPossibleRec(arr, subsetSum, taken,
subset, K, N, curIdx, i - 1);
// after recursive call unmark the element and remove from
// subsetition sum
taken[i] = false;
subsetSum[curIdx] -= arr[i];
if (nxt)
return true;
}
}
return false;
}
// Method returns true if arr can be partitioned into K subsets
// with equal sum
bool isKPartitionPossible(int arr[], int N, int K)
{
// If K is 1, then complete array will be our answer
if (K == 1)
return true;
// If total number of partitions are more than N, then
// division is not possible
if (N < K)
return false;
// if array sum is not divisible by K then we can't divide
// array into K partitions
int sum = 0;
for (int i = 0; i < N; i++)
sum += arr[i];
if (sum % K != 0)
return false;
// the sum of each subset should be subset (= sum / K)
int subset = sum / K;
int subsetSum[K];
bool taken[N];
// Initialize sum of each subset from 0
for (int i = 0; i < K; i++)
subsetSum[i] = 0;
// mark all elements as not taken
for (int i = 0; i < N; i++)
taken[i] = false;
// initialize first subsubset sum as last element of
// array and mark that as taken
subsetSum[0] = arr[N - 1];
taken[N - 1] = true;
// call recursive method to check K-substitution condition
return isKPartitionPossibleRec(arr, subsetSum, taken,
subset, K, N, 0, N - 1);
}
// Driver code to test above methods
int main()
{
int arr[] = {2, 1, 4, 5, 3, 3};
int N = sizeof(arr) / sizeof(arr[0]);
int K = 3;
if (isKPartitionPossible(arr, N, K))
cout << "Partitions into equal sum is possible.\n";
else
cout << "Partitions into equal sum is not possible.\n";
}