如果列出了n
个数字和总和s
,请将这些数字分组到two
个组中,以使每个组中的数字总和为less than or equal to s
。如果可以分组,请打印YES
,如果无法分组,请打印NO
。
例如,如果n=3 , s=4
和n
数字为2,4,2
。
在这种情况下,输出为YES
,因为可以形成的两个组是(2,2) and (4)
。
我的解决方案如下。
A
是包含n个数字的整数数组。
first group
包含第一组中的元素总和。
second group
包含第二组中元素的总和。
解决方案1
s
。sum of all elements
减去sum of elements in second group
如果每个组中的元素总和小于或等于s
,则打印YES
否则打印NO
。
qsort (A, n, sizeof(int),compare);
int second_group=0;
f=0;
for(i=0;i<n;++i)
{
if((second_group+A[i])==s)
{
f=1;
break;
}
else if((second_group+A[i])<s)
{
second_group+=A[i];
}
}
int first_group=sum_of_all_elements-second_group;
if(f==1)
{
cout<<"YES\n";
}
else if ((second_group<=s) && (first_group<=s))
{
cout<<"YES\n";
}
else
{
cout<<"NO\n";
}
解决方案2
使用Greedy approach
如果两个组的元素总和等于sum_of_all_elements
,则打印YES
否则打印NO
。
qsort (A, n, sizeof(int),compare);
int first_group=0,second_group=0;
f=0;
first_group=A[0];
for(i=1;i<n;++i)
{
if(first_group<second_group)
{
if((first_group+A[i])<=s)
first_group+=A[i];
}
else
{
if((second_group+A[i])<=s)
second_group+=A[i];
}
}
if((first_group+second_group)==sum_of_all_elements)
cout<<"YES\n";
else
cout<<"NO\n";
问题
上述两种解决方案都给出了错误答案。我无法理解他们失败的场景。
如果有人可以帮助我解决这个问题的任何其他替代解决方案,那就太棒了。
答案 0 :(得分:1)
您假设所有最小的元素都在一个组中,这不一定是真的。
采用以下示例:
array = {1, 2, 4, 6} , s = 7
对于上述情况,您的两种解决方案都会产生错误的输出。
首先让我澄清一下你要解决的问题。您正在尝试解决Subset Sum Problem的修改版本。让我为你重新解释一下这个问题:
1. Give an array A and a sum S. Find the subset of A with the largest sum S1
such that S1 <= S. (We want the largest sum because it will give the
smallest possible sum for the rest of the elements).
2. Now the sum of the rest of the elements is S2 = TotalSum - S1. If S2 <= S,
print YES otherwise print NO.
子集和问题是NP难问题,不能在多项式时间内求解。但是,存在基于动态编程的Pseudo-Polynomial Time算法。有关伪多项式解,请参阅Subset Sum Problem或Dynamic Programming: Subset Sum。这个想法是这样的:
Use dynamic programming to calculate whether there is a solution to the
subset sum problem for sum = S. If there is a solution, then report YES
if TotalSum - S <= S. Otherwise pick the largest sum that exists in the
DP table (just select the last row with subset sum = True entry in the
last column). Let this sum be S1.
If S1 <= S report YES otherwise NO.
通过在构建DP时记住额外信息,您还可以记住导致您为第一个子集选择的总和S1的子集。
答案 1 :(得分:0)
快速尝试 - A的总和必须<= 2 * s。 A中最大的元素必须是&lt; = s。
你能提供更多的测试案例吗?或者只是我的algh无法工作的情况。
答案 2 :(得分:0)
Group1 =&lt; s和group2 =&lt;小号 所以 group1 + group =数字之和=&lt; 2 * S 所以我建议使用简单的算法,
如果数字总和=&lt; 2 * s
返回true
否则
返回false
答案 3 :(得分:0)
首先对数字进行排序。第一组(sum1)由最大数字组成+与小数字一样多。其他数字转到第二组。
如果数字总和> 2 * s返回false;
按升序对数组进行排序
i = 1; sum1 = a [n]; SUM2 = 0;
while(sum1 + a [i] =&lt; s)
总和1 =总和1 + a [i]
i ++
结束时
表示j = i到n -1
sum2 = sum2 + a [j]
结束
如果(sum1 =&lt; s)和(sum2 =&lt; s)返回true
否则返回false;