Dynamic programming 使用动态规划确定给定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

我找到了一个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< 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];
}

这是一个错误的代码这是一个错误的代码