部分和問題 (dfs搜尋 尺取)
阿新 • • 發佈:2018-11-08
部分和問題
給定整數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;
}