Dynamic programming 使用动态规划确定给定n个数是否有3个分区
我找到了一个3-划分问题的解决方案,即,给定n个数,确定是否可以形成三个不相交的子集,使得所有子集都相等,也就是说,每个子集的和等于n个数/3的和 类似的问题在:。然而,我正在寻找下面代码的解释 简单地说,我不知道发生了什么事。我不知道t是什么,I或j是什么,k是什么,或者为什么k和j从N开始并被递减,t[j+C[I]][k]=true;T[j][k+C[i]]=真平均值,或者我们为什么返回T[N/3]Dynamic programming 使用动态规划确定给定n个数是否有3个分区,dynamic-programming,partition-problem,Dynamic Programming,Partition Problem,我找到了一个3-划分问题的解决方案,即,给定n个数,确定是否可以形成三个不相交的子集,使得所有子集都相等,也就是说,每个子集的和等于n个数/3的和 类似的问题在:。然而,我正在寻找下面代码的解释 简单地说,我不知道发生了什么事。我不知道t是什么,I或j是什么,k是什么,或者为什么k和j从N开始并被递减,t[j+C[I]][k]=true;T[j][k+C[i]]=真平均值,或者我们为什么返回T[N/3] bool T[10240][10000]; bool partition( vector&l
bool T[10240][10000];
bool partition( vector< int > C ) {
// compute the total sum
int n = C.size();
int N = 0;
for( int i = 0; i < n; i++ ) N += C[i];
// initialize the table
T[0][0] = true;
memset(T, 0, 10000^2);
// process the numbers one by one
for( int i = 0; i < n; i++ ) {
for (int j = N; j >= 0; --j) {
for (int k = N; k >= 0; --k) {
if (T[j][k]) {
T[j + C[i]][k] = true;
T[j][k + C[i]] = true;
}
}
}
}
return T[N / 3];
}
首先,返回值应该是T[N/3][N/3] T[i][j]表示是否有可能得到第一个和i之和的分区,以及第二个和j之和的分区。显然,因为所有n个数的和都是n。所以T[i][j]为真意味着数组可以分成三个分区,其和分别为i、j和n-i-j 最初,T[0][0]为真,其他所有为假,这意味着在一开始,只能将数字划分为三个分区:0、0和N。i的for循环迭代所有N个数字,每次,数字C[i]可以分为第一个分区或第二个分区。这就是为什么把T[j+C[i][k]和T[j][k+C[i]]设为真
变量j和k从N开始递减的原因是为了避免一个数字重复计数。以这种方式考虑:例如,如果j从0开始到n,则t[j] [k],t[j+c[i] [k],t[j+c[i] * 2 ] [k],…T[j+C[i]*x][k]都将设置为真,这是不正确的。您只需选择一个小案例,自己尝试模拟流程。首先,返回值应为T[N/3][N/3] T[i][j]表示是否有可能得到第一个和i之和的分区,以及第二个和j之和的分区。显然,因为所有n个数的和都是n。所以T[i][j]为真意味着数组可以分成三个分区,其和分别为i、j和n-i-j 最初,T[0][0]为真,其他所有为假,这意味着在一开始,只能将数字划分为三个分区:0、0和N。i的for循环迭代所有N个数字,每次,数字C[i]可以分为第一个分区或第二个分区。这就是为什么把T[j+C[i][k]和T[j][k+C[i]]设为真
变量j和k从N开始递减的原因是为了避免一个数字重复计数。以这种方式考虑:例如,如果j从0开始到n,则t[j] [k],t[j+c[i] [k],t[j+c[i] * 2 ] [k],…T[j+C[i]*x][k]都将设置为真,这是不正确的。你可以简单地挑选一个小的例子来尝试自己模拟这个过程。 < P>正确的C++实现,看起来是这样的:
int partition3(vector<int> &A)
{
int sum = accumulate(A.begin(), A.end(), 0);
if (sum % 3 != 0)
{
return false;
}
int size = A.size();
vector<vector<int>> dp(sum + 1, vector<int>(sum + 1, 0));
dp[0][0] = true;
// process the numbers one by one
for (int i = 0; i < size; i++)
{
for (int j = sum; j >= 0; --j)
{
for (int k = sum; k >= 0; --k)
{
if (dp[j][k])
{
dp[j + A[i]][k] = true;
dp[j][k + A[i]] = true;
}
}
}
}
return dp[sum / 3][sum / 3];
}
<正确的C++实现方式如下:
int partition3(vector<int> &A)
{
int sum = accumulate(A.begin(), A.end(), 0);
if (sum % 3 != 0)
{
return false;
}
int size = A.size();
vector<vector<int>> dp(sum + 1, vector<int>(sum + 1, 0));
dp[0][0] = true;
// process the numbers one by one
for (int i = 0; i < size; i++)
{
for (int j = sum; j >= 0; --j)
{
for (int k = sum; k >= 0; --k)
{
if (dp[j][k])
{
dp[j + A[i]][k] = true;
dp[j][k + A[i]] = true;
}
}
}
}
return dp[sum / 3][sum / 3];
}
这是一个错误的代码这是一个错误的代码