Problem p02271 (C++)

Buggy submission (status: Runtime Error):
// 全探索
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stack>

using namespace std;

const int MAX_N = 20;
const int MAX_N_2 = 1000000;
const int MAX_Q = 200;

// 入力値を保持するバッファ
int input_buffer[MAX_N + 1];
// 組み合わせの管理用バッファ
int comb_buffer[MAX_N + 1];
// 組み合わせから求めた和を格納する配列
int pos = 0;
int add_buffer[MAX_N_2];

void combinations(int n, int r);
void comb_sub(int n, int r, int m);
void add_combination(int m);

int main(void) {
  int n, q, Q[MAX_Q + 1];

  scanf("%d", &n);

  for (int i = 0; i < n; i++) {
    scanf("%d", &input_buffer[i]);
  }

  scanf("%d", &q);

  for (int i = 0; i < q; i++) {
    scanf("%d", &Q[i]);
  }

  for (int i = 0; i < n; i++) {
    combinations(n, i);
  }

  for (int i = 0; i < q; i++) {
    bool judge = false;

    for (int j = 0; j < pos; j++) {
      if (add_buffer[j] == Q[i]) {
        judge = true;
        break;
      }
    }

    if (judge) {
      printf("yes\n");
    } else {
      printf("no\n");
    }
  }

  return 0;
}

// 組み合わせを生成する関数の入り口
void combinations(int n, int r) {
  if (r > 0 && r <= MAX_N) {
    comb_sub(n, r, 0);
  }
}

// 組み合わせを生成する関数
// n : 選択する数値の範囲 ( 1〜 n )
// r : 選ぶ数値の個数
// m : 選んだ数値の個数
void comb_sub(int n, int r, int m) {
  if (r == 0) {
    // r が 0 になったので、組み合わせを一つ生成できた
    add_combination(m);
  } else if (n == r) {
    for (int i = r; i > 0; i--) {
      // n が r と等しくなったならば、残りの数字 (1 から r まで) を全て選択
      comb_buffer[m++] = i;
    }

    add_combination(m);
  } else {
    // nを選ばない場合
    // 残りの数字の中から r 個の数字を選びます。
    comb_sub(n - 1, r, m);

    // nを選ぶ場合
    // 数字 n を comb_buffer に追加して、残りの数字の中から r - 1 個を選びます。
    comb_buffer[m] = n;
    comb_sub(n - 1, r - 1, m + 1);
  }

  return;
}

// 入力数値の和を求める
void add_combination(int m) {
  // 配列の初期化
  add_buffer[pos] = 0;

  for (int i = 0; i < m; i++) {
    // 入力された数列の和を順番に求める
    add_buffer[pos] += input_buffer[comb_buffer[i] - 1];
  }

  // 要素を進める
  pos++;

  return;
}


Fixed submission:
// 全探索
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stack>

using namespace std;

const int MAX_N = 20;
const int MAX_N_2 = 10000000;
const int MAX_Q = 200;

// 入力値を保持するバッファ
int input_buffer[MAX_N + 1];
// 組み合わせの管理用バッファ
int comb_buffer[MAX_N + 1];
// 組み合わせから求めた和を格納する配列
int pos = 0;
int add_buffer[MAX_N_2];

void combinations(int n, int r);
void comb_sub(int n, int r, int m);
void add_combination(int m);

int main(void) {
  int n, q, Q[MAX_Q + 1];

  scanf("%d", &n);

  for (int i = 0; i < n; i++) {
    scanf("%d", &input_buffer[i]);
  }

  scanf("%d", &q);

  for (int i = 0; i < q; i++) {
    scanf("%d", &Q[i]);
  }

  for (int i = 0; i < n; i++) {
    combinations(n, i);
  }

  for (int i = 0; i < q; i++) {
    bool judge = false;

    for (int j = 0; j < pos; j++) {
      if (add_buffer[j] == Q[i]) {
        judge = true;
        break;
      }
    }

    if (judge) {
      printf("yes\n");
    } else {
      printf("no\n");
    }
  }

  return 0;
}

// 組み合わせを生成する関数の入り口
void combinations(int n, int r) {
  if (r > 0 && r <= MAX_N) {
    comb_sub(n, r, 0);
  }
}

// 組み合わせを生成する関数
// n : 選択する数値の範囲 ( 1〜 n )
// r : 選ぶ数値の個数
// m : 選んだ数値の個数
void comb_sub(int n, int r, int m) {
  if (r == 0) {
    // r が 0 になったので、組み合わせを一つ生成できた
    add_combination(m);
  } else if (n == r) {
    for (int i = r; i > 0; i--) {
      // n が r と等しくなったならば、残りの数字 (1 から r まで) を全て選択
      comb_buffer[m++] = i;
    }

    add_combination(m);
  } else {
    // nを選ばない場合
    // 残りの数字の中から r 個の数字を選びます。
    comb_sub(n - 1, r, m);

    // nを選ぶ場合
    // 数字 n を comb_buffer に追加して、残りの数字の中から r - 1 個を選びます。
    comb_buffer[m] = n;
    comb_sub(n - 1, r - 1, m + 1);
  }

  return;
}

// 入力数値の和を求める
void add_combination(int m) {
  // 配列の初期化
  add_buffer[pos] = 0;

  for (int i = 0; i < m; i++) {
    // 入力された数列の和を順番に求める
    add_buffer[pos] += input_buffer[comb_buffer[i] - 1];
  }

  // 要素を進める
  pos++;

  return;
}