Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void calc_pathes(const vi& x, const vi& y, const vi& z, vi& mode, vvi& path)
- {
- const int n = isz(mode);
- const int m = isz(path);
- // Перебираю все пары путей из i в j
- for (int i = 0; i < m; ++i) {
- for (int j = i; j < m; ++j) {
- if (i == j) continue;
- // сколько нужно по модулю пройти расстояние
- int total = abs(x[j] - x[i]) + abs(y[j] - y[i]) + abs(z[j] - z[i]);
- // Делаю bfs в 1мерном пространстве
- queue<pair<int, int>> q; // шаги, текущая позиция (нам нужен total)
- q.push(make_pair(0, 0));
- vi dist(total + 1, INF);
- while (!q.empty()) {
- auto [step, curr] = q.front();
- q.pop();
- if(curr > total) curr %= total; // иногда есть вариант перебежать и вернуться, поэтому берём по модулю
- if (dist[curr] <= step) continue;
- dist[curr] = step;
- for (int k = 0; k < n; ++k)
- q.push(make_pair(step + 1, curr + mode[k]));
- }
- path[i][j] = path[j][i] = dist[total];
- }
- }
- }
- void solve()
- {
- int n, m; cin >> n >> m;
- vi mode(n); cin >> mode;
- vi x(m + 1), y(m + 1), z(m + 1); // создаю ещё фиктивную вершину в (0,0,0)
- for (int i = 1; i <= m; ++i)
- cin >> x[i] >> y[i] >> z[i];
- vvi path(m + 1, vi(m + 1, INF));
- for (int i = 0; i <= m; ++i)
- path[i][i] = 0;
- calc_pathes(x, y, z, mode, path);
- for (int i = 0; i <= m; ++i) {
- for (int j = 0; j <= m; ++j)
- if (path[i][j] == INF) { // Должен быть связным граф
- std::cout << -1 << '\n';
- return;
- }
- }
- ++m;
- vvi dp(1 << m, vi(m, INF));
- dp[1][0] = 0;
- for (int mask = 1; mask < (1 << m); ++mask) {
- // Т.к. стартуем в 0 вершине, то старт из других вершин отсекаем
- int cnt{};
- for (int i = 0; i < m; ++i)
- cnt += get_bit(mask, i);
- // когда маска вида 0..010..0
- if (cnt == 1 && mask != 1) continue;
- for (int i = 0; i < m; ++i) {
- for (int j = 0; j < m; ++j) {
- // i - где мы стоим, j - куда идём
- if (get_bit(mask, i) && i != j) {
- int total = dp[mask][i] + path[i][j];
- if (total < dp[mask | (1 << j)][j])
- dp[mask | (1 << j)][j] = total;
- }
- }
- }
- }
- int answ = INF;
- for (int i = 1; i < m; ++i)
- if (dp[(1 << m) - 1][i] < answ)
- answ = dp[(1 << m) - 1][i];
- std::cout << answ << '\n';
- }
Advertisement
Add Comment
Please, Sign In to add comment