这是子集求和问题的解决方案。它使用回溯。我一直在考虑它超过2个小时,我无法理解它。
编辑:我根据我的理解在代码中添加了一些注释。如果我错了,请纠正我。
#include <iostream>
int n, d, w[10], x[10], count=0;
void subset(int cs, int k, int r)//i dont understand the purpose of cs or of the array x[]
{
int i;
x[k] = 1;
if(cs + w[k] == d) //if the first element is equivalent to the sum that is required
{
std::cout<< "\n\nSolution " << ++count << " is:";
for(i=0; i<=k; i++) // so if the subset criteria are met then the array is printed.
if(x[i] == 1)
std::cout << w[i] << " ";
}
else if(cs + w[k] + w[k+1] <= d) //if the node is promising then go to the next node and
subset(cs + w[k], k+1, r - w[k]); //check if subset criteria are met
if(cs + w[k+1] <= d && cs + r - w[k] >= d) //else backtrack
{
x[k] = 0;
subset(cs, k+1, r-w[k]);
}
}
int main()
{
int sum=0, i;
std::cout << "enter n\n";
std::cin >> n;
std::cout < <"enter " << n << " elements\n";
for(i=0; i<n; i++)
std::cin >> w[i];
for(i=0; i<n; i++)
sum += w[i];
std::cout << "enter value of sum\n";
std::cin >> d;
if(sum < d)
std::cout<<"INVALID SOLUTION\n";
else
subset(0,0,sum);
}
注意:这是一个有效的解决方案。它在使用g ++编译时有效。我很抱歉,如果这看起来太令人讨厌,但我对代码了解不多,因此我无法给出太多解释。
答案 0 :(得分:2)
试试这个。
#include<iostream>
int n,d,w[10],used[10],count=0;
int cs = 0; // cs=Current Sum
void subset(int k)
{
if (k >= n) return; // boundry check
int i;
used[k] = 1; // use element k
cs += w[k];
if(cs == d) {
cout<<"\n\nSolution " << ++count << " is:";
for(i=0;i <= k;i++)
if(used[i]==1)
cout<<w[i]<<" ";
}
if (cs < d) // only when current sum is not enough
subset(k + 1);
used[k] = 0; // not use element k
cs -= w[k];
subset(k+1);
}
void main()
{
int sum=0,i;
cout<<"enter n\n";
cin>>n;
cout<<"enter "<<n<<" elements\n";
for(i=0;i<n;i++)
cin>>w[i];
for(i=0;i<n;i++)
sum+=w[i];
cout<<"enter value of sum\n";
cin>>d;
cs = 0;
if(sum<d)
cout<<"INVALID SOLUTION\n";
else
subset(0);
}
答案 1 :(得分:1)
cs是到目前为止所选择的权重值的总和,而r是尚未选择的权重的总和值的余数。 w [i]是权重i,当选择权重[i]时,x [i]是1。在子集方法中有两个主要的决策分支:
选择重量k:
// adding value of weight k to computed sum (cs) gives required sum, solution found
if(cs+w[k]==d)
{
cout<<"\n\nSolution "<<++count<<" is:";
for(i=0;i<=k;i++)
if(x[i]==1)
cout<<w[i]<<" ";
}
// both weight k and weight k+1 can be chosen without exceeding d,
// so we choose k, and see if there's a solution for weight k+1 onwards
// note that available weight values decreased from r to r-w[k]
else if(cs+w[k]+w[k+1]<=d)
subset(cs+w[k],k+1,r-w[k]);
未选择重量k(注意,即使在选择重量k后立即找到解决方案,也会进行探索):
// weight k+1 is choosable (does not exceed d), and despite not choosing weight k
// there would be sufficient weights in r less w[k], and together with the chosen
// pool cs to meet the requirement of d.
if(cs+w[k+1]<=d && cs+r-w[k]>=d)
{
x[k]=0;
subset(cs,k+1,r-w[k]);
}
答案 2 :(得分:0)
cs是当前的总和,x []是一个数组,对于属于当前正在探索的解决方案分支的那些元素有1个集合。