部分和问题
给定整数a1, a2, a3, a4, .......... , an ,判断是否可以从中取出若干个数,使得他们的和恰好为k 。
1 <= n <= 20
测试数据:n = 4
a[] = {1, 2, 4, 7}
k = 13
这道题数据范围较小,可以用DFS取暴力搜
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int a[25];
int n, k;
bool dfs(int i, int sum){
if(i == n) return sum == k;
if(dfs(i+1, sum)) return true;
if(dfs(i+1, sum + a[i])) return true;
return false;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
scanf("%d", &k);
if(dfs(0, 0)) printf("Yes\n");
else printf("No\n");
}
如果能够组成既定的和,则打印出被选择的数字
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int a[25];
int n, k, cnt = 0;
int res[25];
bool dfs(int i, int sum){
if(i == n) return sum == k;
if(dfs(i+1, sum)) return true;
if(dfs(i+1, sum+a[i])){
res[cnt++] = a[i];
return true;
}
return false;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
scanf("%d", &k);
if(dfs(0, 0)){
printf("Yes\n");
for(int i = 0; i < n; i++) printf("%d ", res[i]);
printf("\n");
}
else printf("No\n");
return 0;
}
问题变形:一个序列中有n个数,问是否存在最小的num(选取的数字个数)使得和大于k,存在输出 "Yes", 否则,输出“No”。
修改:如果n的值特别大时,例如 n = 100 时,如果用DFS的话,会爆栈。所以 要用一种方式去解决这一问题。可以用尺取的方法来做
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 1e6+5;
int a[maxn];
int n, k;
int main()
{
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
int l = 0, r = 0, sum = 0, flag = 0;
while(1){
while(t < n&&sum < k) sum += a[r++];
if(sum < S) break;
res = min(res, r-l);
sum -= a[s++];
}
if(res > n) printf("Yes\n");
else printf("No\n");
return 0;
}