fork download
  1. //Bài toán: Cho n số nguyên dương (n<20) và giá trị S. In ra mọi tập con có tổng đúng bằng S.
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4.  
  5. int n, S;
  6. vector<int> a;
  7. vector<int> chosen;
  8. vector<long long> suffixSum; // suffixSum[i] = a[i] + ... + a[n-1]
  9.  
  10. void backtrack(int i, long long curSum) {
  11. // Cắt tỉa (pruning) để giảm độ phức tạp: tổng vượt quá S rồi thì không cần xét thêm vào phần tử nào nữa
  12. if (curSum > S) return;
  13.  
  14. // Cắt tỉa (pruning) để giảm độ phức tạp:: dù lấy hết phần còn lại cũng không đủ S, không cần xét tiếp nữa
  15. if (i < n && curSum + suffixSum[i] < S) return;
  16.  
  17. // Điều kiện dừng : Nếu đạt đúng S → in kết quả
  18. if (curSum == S) {
  19. for (int x : chosen) cout << x << " ";
  20. cout << "\n";
  21. // Không return ngay, vì có thể còn số 0 phía sau (nếu đề cho)
  22. // Nhưng vì bài toán là số nguyên dương → có thể return để tối ưu
  23. return;
  24. }
  25.  
  26. // Nếu đã xét hết phần tử
  27. if (i == n) return;
  28.  
  29. // CHỌN a[i]
  30. chosen.push_back(a[i]);
  31. // GỌI ĐỆ QUY
  32. backtrack(i + 1, curSum + a[i]);
  33. // BỎ CHỌN a[i] (undo state)
  34. chosen.pop_back();
  35.  
  36. //GỌI ĐỆ QUY TRƯỜNG HỢP KHÔNG CHỌN a[i]
  37. backtrack(i + 1, curSum);
  38. }
  39.  
  40. int main() {
  41. cin >> n >> S;
  42. a.resize(n);
  43. for (int i = 0; i < n; i++) cin >> a[i];
  44.  
  45.  
  46. // Tính suffix sum
  47. suffixSum.assign(n, 0);
  48. suffixSum[n - 1] = a[n - 1];
  49. for (int i = n - 2; i >= 0; i--)
  50. suffixSum[i] = suffixSum[i + 1] + a[i];
  51.  
  52. backtrack(0, 0);
  53. }
Success #stdin #stdout 0.01s 5292KB
stdin
5 6
1 2 3 4 5
stdout
1 2 3 
1 5 
2 4