我试图解决以下问题,但我仍然得到错误答案,但问题中的两个测试用例对我来说是正确答案。
问题陈述:快捷方式的子集Sum或“SS”(双S)是计算机科学中的经典问题。
我们得到一组正整数;我们必须知道这个集合中是否存在非空子集,其元素之和等于给定数量。
例如:假设集合为[3,4,7,9,10]且目标数为20,子集[3,7,10]的元素总和等于20.
输入格式:输入由许多测试用例组成,每个测试用例由两行组成。在输入文件的第一行,有一个数字表示测试用例的数量。每个测试用例的第一行具有两个整数(k,n):k是目标数,n <= 10是该组的元素数。在第二行有n个整数,每个数字都小于一百。
输出格式:对于每个测试用例,如果有一个满足上述条件的子集,则打印“YES”而不带引号,否则为“NO”。
Sample Input:
2
1 5
45 26 36 4 8
49 8
49 9 5 37 0 42 15 19
Sample Output:
NO
YES
您可以在此处测试提交内容:http://www.a2oj.com/p.jsp?ID=151
My Code:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
bool check = false;
void get(vector<int> arr, long total, int i, int k)
{
int length = arr.size() - 1;
if (i == length*length || i == length)
return;
if (total == k)
{
check = true;
return;
}
if (total >= k && i <= 1)
{
check = false;
return;
}
get(arr, total + arr[i], i + 1, k);
get(arr, total, i + 1, k);
}
int main(void) {
int t;
cin >> t;
vector<int> arr;
while (t--)
{
arr.clear();
int n, k;
cin >> n >> k;
for (int i = 0; i < k; i++)
{
int n;
cin >> n;
arr.push_back(n);
}
get(arr, 0, 0, n);
// arr = { 49,9,5,37,0,42,15,19 };
// get(arr, 0, 0, 49);
if (check)
cout << "YES" << endl;
else
cout << "NO" << endl;
check = false;
}
return 0;
}
答案 0 :(得分:2)
我会这样做:
bool SS(const std::vector<int>& v, int total)
{
std::set<int> sums;
for (auto e : v) {
std::set<int> r = sums;
r.insert(e);
for (auto s : sums) {
r.insert(s + e);
}
sums.swap(r);
}
return sums.count(total);
}
其中std::set
总和内容是给定向量的所有可能总和。
答案 1 :(得分:1)
在get
函数的最后一行,您将覆盖先前递归调用计算的值。
get(arr, total + arr[i], i + 1, k);
get(arr, total, i + 1, k);
因此,如果第一个电话将check
设置为true
而第二个电话将其设置为false
,则您将丢失第一个电话。这是使用全局变量被认为有害的原因之一,特别是在递归函数中。
您应该更改get
函数以返回布尔值,而不是定义全局变量,然后您可以像这样递归:
return get(arr, total + arr[i], i + 1, k) || get(arr, total, i + 1, k);
还尝试使用更有意义的变量/函数名称。例如,您的递归函数可以具有以下原型:
bool addsUp(vector<int> array, int total, int from, int length);
对于k
函数中的n
和main
变量,我认为您应该更换其名称以符合问题陈述(k
是所需的总数,n
是数字的数量。)
最后你的边界条件似乎不太对劲。这是我接受的递归函数:
bool addsUp(vector<int> arr, long soFar, int from, int total) {
if (total == 0)
return false;
if (soFar == total)
return true;
if (soFar > total)
return false;
if (from >= arr.size())
return false;
return addsUp(arr, soFar + arr[from], from + 1, total) || addsUp(arr, soFar, from + 1, total);
}
答案 2 :(得分:1)
我有一个递归代码,你可以尝试一下,
#include <iostream>
#include <vector>
bool find_subset(const std::vector<int>& input_data, int N, int target_value)
{
if (N == 1)
return input_data[0] == target_value;
bool result = false;
for (int i = 0; i < N; ++i)
{
std::vector<int> copy = input_data;
copy.erase(copy.begin() + i);
if (input_data[i] == target_value || find_subset(copy, N - 1, target_value - input_data[i]))
{
result = true;
break;
}
}
return result;
}
int main()
{
std::vector<int> test_1{45, 26, 36, 4, 8}; int target_1 = 1;
std::vector<int> test_2{49, 9, 5, 37, 0, 42, 15, 19}; int target_2 = 49;
std::vector<int> test_3{ 1, 3, 5, 7 }; int target_3 = 13;
std::vector<int> test_4{ 1, 3, 5, 7 }; int target_4 = 14;
std::cout << (find_subset(test_1, test_1.size(), target_1) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_2, test_2.size(), target_2) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_3, test_3.size(), target_3) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_4, test_4.size(), target_4) ? "Yes" : "No") << std::endl;
return 0;
}
输出为:
No
Yes
Yes
No