Problem p02604 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

struct city {
  int x;
  int y;
  int64_t p;
};

struct linescore {
  int lineid;
  int l;
  int64_t s;
};

int64_t recursive_score(int K, int N, vector<int> &candidate_lines,
                        vector<vector<linescore>> &city_line_scores,
                        int min_select, int selected_num,
                        vector<bool> &selected_lines, int64_t lower_bound) {
  if (selected_num == K) {
    int64_t s = 0;
    for (int i = 0; i < N; i++) {
      // 各都市の一番近い線のスコアを合計
      for (auto line_score : city_line_scores[i]) {
        if (selected_lines[line_score.lineid]) {
          s += line_score.s;
          if (s > lower_bound) {
            return s;
          }
          break;
        }
      }
    }
    return s;
  }

  int64_t min_score = lower_bound;
  for (int i = min_select; i < (int)candidate_lines.size(); i++) {
    int next_min_select;
    if (i % 2 == 0) {
      next_min_select = i + 2; // 同じ都市に縦線と横線を両方置くのは無駄
    } else {
      next_min_select = i + 1;
    }

    selected_lines[i] = true;
    int64_t s = recursive_score(K, N, candidate_lines, city_line_scores,
                                next_min_select, (selected_num + 1),
                                selected_lines, min_score);
    selected_lines[i] = false;

    min_score = min(min_score, s);
  }
  return min_score;
}

int main() {
  int N;
  cin >> N;
  vector<city> cities(N);
  for (int i = 0; i < N; i++) {
    int x, y, p;
    cin >> x;
    cin >> y;
    cin >> p;
    cities[i] = city{x, y, p};
  }

  // 線の候補
  vector<int> candidate_lines;
  for (int j = 0; j < N; j++) {
    int xj = cities[j].x;
    int yj = cities[j].y;

    candidate_lines.push_back(xj * 2);
    candidate_lines.push_back(yj * 2 + 1);
  }

  // 線-都市ペアでのスコア事前計算
  vector<vector<linescore>> city_line_scores(N);
  for (int i = 0; i < N; i++) {
    int xi = cities[i].x;
    int yi = cities[i].y;
    int64_t pi = cities[i].p;

    vector<linescore> line_score;

    for (int j = 0; j < N; j++) {
      int xj = cities[j].x;
      int yj = cities[j].y;

      line_score.push_back(linescore{j * 2, xj * 2, pi * abs(xi - xj)});
      line_score.push_back(linescore{j * 2 + 1, yj * 2 + 1, pi * abs(yi - yj)});
    }
    line_score.push_back(linescore{N * 2, 0, pi * abs(xi)});
    line_score.push_back(linescore{N * 2 + 1, 1, pi * abs(yi)});
    sort(line_score.begin(), line_score.end(),
         [](linescore a, linescore b) { return a.s < b.s; });
    city_line_scores[i] = line_score;
  }

  int64_t lower_bound = 1000000000000000LL;
  for (int K = 0; K < N; K++) {
    vector<bool> selected_lines(N * 2 + 2);
    for (int j = 0; j < N; j++) {
      selected_lines[j * 2] = false;
      selected_lines[j * 2 + 1] = false;
    }
    selected_lines[N * 2] = true;
    selected_lines[N * 2 + 1] = true;
    int64_t S = recursive_score(K, N, candidate_lines, city_line_scores, 0, 0,
                                selected_lines, lower_bound);
    cout << S << endl;
    lower_bound = S;
  }
  cout << 0 << endl;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

struct city {
  int64_t x;
  int64_t y;
  int64_t p;
};

struct linescore {
  int64_t l;
  int64_t s;
};

int64_t recursive_score(int64_t K, int64_t N, vector<int64_t> &candidate_lines,
                        vector<vector<linescore>> &city_line_scores,
                        int64_t min_select, int64_t selected_num,
                        vector<int64_t> &selected_lines,
                        unordered_set<int64_t> &zeroscore) {
  if (K == N) {
    return 0;
  }

  if (selected_num == K) {
    // cout << "=================" << endl;
    // for (auto ss : selected_lines) {
    //   if (ss == 0 || ss == 1) {
    //     continue;
    //   }
    //   if (ss % 2 == 0) {
    //     cout << (ss / 2) << " V "
    //          << " " << K << endl;
    //   } else {
    //     cout << ((ss - 1) / 2) << " H "
    //          << " " << K << endl;
    //   }
    // }

    int64_t s = 0;
    for (int64_t i = 0; i < N; i++) {
      // 各都市の一番近い線のスコアを合計
      bool found = false;
      for (auto line_score : city_line_scores[i]) {
        for (int64_t sl = 0; sl < K + 2; sl++) {
          if (selected_lines[sl] == line_score.l) {
            s += line_score.s;
            found = true;
            break;
          }
        }
        if (found) {
          break;
        }
      }
    }
    return s;
  }

  int64_t min_score = 100000000000000LL;
  for (int64_t i = min_select; i < (int64_t)candidate_lines.size(); i++) {
    int64_t next_min_select;
    if (i % 2 == 0) {
      next_min_select = i + 2; // 同じ都市に縦線と横線を両方置くのは無駄
    } else {
      next_min_select = i + 1;
    }

    selected_lines[selected_num + 2] = candidate_lines[i];
    int64_t s = recursive_score(K, N, candidate_lines, city_line_scores,
                                next_min_select, (selected_num + 1),
                                selected_lines, zeroscore);

    if (s == 0) {
      return 0;
    }
    min_score = min(min_score, s);
  }
  return min_score;
}

int main() {
  int64_t N;
  cin >> N;
  vector<city> cities(N);
  for (int64_t i = 0; i < N; i++) {
    int64_t x, y, p;
    cin >> x;
    cin >> y;
    cin >> p;
    cities[i] = city{x, y, p};
  }

  // 線の候補
  vector<int64_t> candidate_lines;
  for (int64_t j = 0; j < N; j++) {
    int64_t xj = cities[j].x;
    int64_t yj = cities[j].y;

    candidate_lines.push_back(xj * 2);
    candidate_lines.push_back(yj * 2 + 1);
  }

  // 線-都市ペアでのスコア事前計算
  vector<vector<linescore>> city_line_scores(N);
  for (int64_t i = 0; i < N; i++) {
    int64_t xi = cities[i].x;
    int64_t yi = cities[i].y;
    int64_t pi = cities[i].p;

    vector<linescore> line_score;

    for (int64_t j = 0; j < N; j++) {
      int64_t xj = cities[j].x;
      int64_t yj = cities[j].y;

      line_score.push_back(linescore{xj * 2, pi * abs(xi - xj)});
      line_score.push_back(linescore{yj * 2 + 1, pi * abs(yi - yj)});
    }
    line_score.push_back(linescore{0, pi * abs(xi)});
    line_score.push_back(linescore{1, pi * abs(yi)});
    sort(line_score.begin(), line_score.end(),
         [](linescore a, linescore b) { return a.s < b.s; });
    city_line_scores[i] = line_score;
  }

  for (int64_t K = 0; K <= N; K++) {
    unordered_set<int64_t> zeroscore;

    vector<int64_t> selected_lines(N + 2);

    selected_lines[0] = 0;
    selected_lines[1] = 1;
    int64_t S = recursive_score(K, N, candidate_lines, city_line_scores, 0, 0,
                                selected_lines, zeroscore);
    cout << S << endl;
  }
}