У меня есть массив A = {-8, -5,0, -3,8,8,2, -2}, я хочу рассчитать минимальное количество ходов, необходимое для того, чтобы все элементы массива 0 использовали только элементы массива, учитывая следующее условие ->

1. элемент с индексом x может быть перемещен непосредственно в позицию x + 1, x + 2 или позицию x-1, x-2 за один ход, после этого счетчик ходов увеличится.

  1. ни один элемент не может быть перемещен до начального индекса массива, то есть 0, и после конечного индекса, то есть длины массива.

Например в массиве выше минимального хода будет 31:

  1. все 8 элементов с индексом 4 можно переместить в индекс 0 всего за 16 ходов (потому что для всех 8 элементов требуется 2 хода). ходов: 16.
  2. 3 элемента из индекса 5 могут быть перемещены в индекс 3 за 3 хода (3 элемента занимают по 1 ходу каждый), а оставшиеся 5 элементов из индекса 5 могут быть перемещены в индекс 2 за 10 ходов (5 элементов требуют 2 хода, поэтому всего 10 ходов) . ходов = 16 + 3 + 10 = 29.
  3. 2 элемента из индекса 6 перемещаются в индекс 7 за 2 хода (по 1 ходу). ходов = 29 + 2 = 31.

Возьмем другой пример для входного массива {-1, -1,0,1,1}, оптимальное решение дает ответ 3 следующим образом -> 1 из индекса 3 перемещается в индекс 1 за 1 ход, затем 1 из индекса 4 перемещается в индекс 0 за 2 хода, поэтому всего ходов будет 3.

Я пробовал писать код на C ++, но не нашел оптимального решения, а также не смог охватить все сценарии.

Ниже мой код, но не в рабочем состоянии

int solution1(vector < int > & c) {

  int alen = c.size();
  if (alen == 0) return -1;

  int move = 0;
  int moved = 0;
  for (int j = 0; j < alen; ++j) {
    if (c[j] < 0) {
      for (int k = j + 1; k < alen; ++k) {
        moved = 0;
        if (c[k] > 0) {
          c[j] = 0 - c[j];
          if (c[j] <= c[k]) {
            c[k] = c[k] - c[j];
            moved = c[j];
            c[j] = 0;
          } else {
            c[j] = c[k] - c[j];
            moved = c[k];
            c[k] = 0;
          }
          if (k - j >= 2) {
            if ((k - j) % 2)
              move += ((k - j + 1) / 2) * moved;
            else
              move += ((k - j) / 2) * moved;
          } else {
            move += moved;
          }
          if (c[j] == 0) break;
        }
      }
    } else if (c[j] > 0) {
      for (int kk = j + 1; kk < alen; ++kk) {
        moved = 0;
        if (c[kk] < 0) {
          c[kk] = 0 - c[kk];
          if (c[j] <= c[kk]) {
            c[kk] = c[j] - c[kk];
            moved = c[j];
            c[j] = 0;
          } else {
            c[j] = c[j] - c[kk];
            moved = c[kk];
            c[kk] = 0;
          }
          if (kk - j >= 2) {
            move += ((kk - j) / 2) * moved;
          } else {
            move += moved;
          }
          if (c[j] == 0) break;

        }
      }
    }

  }
  if (move > 0) return move;
  else return -1;
}
0
Shobhit Chaturvedi 23 Сен 2018 в 10:49

1 ответ

Лучший ответ

Данная проблема требует конструктивного решения. Поскольку диапазон перемещения простирается до (x - 2, x + 2) , мы поддерживаем массив overhead размера 2, который поддерживает стоимость перемещения элементов при переходе от i в (i + 1) th позицию для четных и нечетных индексов. Мы перебираем данный массив слева направо и вычисляем стоимость перемещения всех оставшихся элементов влево от индекса i . Такую стоимость можно рассчитать с помощью массива накладных расходов (см. Код ниже). Если на любом этапе существует возможность отмены некоторых отрицательных целых чисел положительными целыми числами, мы сначала выбираем те элементы, которые стоили бы нам +1, если бы он переместился с i на ( i + 1) в нашем следующем шаге для процесса нейтрализации.

Суть наблюдения заключается в том, что если мы продолжаем перемещать элемент с индексом x слева направо, это только увеличивает стоимость перемещений в точках (x + 1), (x + 3), (x + 5), ... и так далее. Вот работающий код для того же: https://ideone.com/TFunNG

int solve(vector<int> v) {
    vector<int> overhead(2,0);
    int num_of_moves = 0, sum = 0;
    for(int i = 0; i < v.size(); i++) {
        num_of_moves += overhead[i % 2];
        int left = abs(v[i]);
        if((sum > 0 && v[i] < 0) || (sum < 0 && v[i] > 0)) {
            int used = min(abs(sum), abs(v[i]));
            int diff = min(overhead[(i + 1) % 2], used);
            overhead[(i + 1) % 2] -= diff;
            overhead[i % 2] -= min(overhead[i % 2], (used - diff));
            left -= used;
        }
        sum += v[i];
        overhead[(i + 1) % 2] += abs(left);
    }

    assert(sum == 0);
    return num_of_moves;
}

Общая сложность выполнения решения составляет O (n) .

1
Nilesh 23 Сен 2018 в 20:28