部分和问题 (dfs搜索 尺取)

                                                          部分和问题

给定整数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;
} 

猜你喜欢

转载自blog.csdn.net/qq_41818544/article/details/83748221