Максимальное количество символов при нажатии клавиш A, Ctrl + A, Ctrl + C и Ctrl + V


106

Это вопрос для интервью от Google. Сам не могу решить. Может кто-нибудь пролить свет?

Напишите программу для печати последовательности нажатий клавиш так, чтобы она генерировала максимальное количество символов «А». Вам разрешается использовать только 4 клавиши: A, Ctrl+ A, Ctrl+ Cи Ctrl+ V. Допускается только N нажатий клавиш. Все Ctrlсимволы + считаются одним нажатием клавиши, поэтому Ctrl+ A- одним нажатием клавиши.

Так , например, последовательность A, Ctrl+ A, Ctrl+ C, Ctrl+ Vгенерирует два в 4 - й в нажатиях клавиша.

  • Ctrl + A - выбрать все
  • Ctrl + C - Копировать
  • Ctrl + V - это вставить

Я немного по математике. Для любого N, используя x чисел A, one Ctrl+ A, one Ctrl+ Cи y Ctrl+ V, мы можем сгенерировать max ((N-1) / 2) 2 числа A. Для некоторого N> M, то лучше использовать , как много Ctrl+ A«s, Ctrl+ Cи Ctrl+ Vпоследовательности , как это удваивает количество в.

Последовательность Ctrl+ A, Ctrl+ V, Ctrl+ Cне перезапишет существующий выбор. Он добавит скопированный выбор к выбранному.


Во многих текстовых редакторах ^Aобычно бывает «выбрать все», ^C«копировать», ^V«вставить». Это дает вам представление?
Николай Фетисов 05

Я имею в виду количество пятерок. Например, для N = 7 мы можем напечатать 9 A, используя нажатия клавиш A, A, A, CTRL + A, CTRL + C, CTRL + V, CTRL + V
munda

Это 7 нажатий клавиш.
Джон Диблинг 05

@John "Все символы CTRL + считаются одним нажатием клавиши, поэтому CTRL + A - это одно нажатие клавиши."
fredley 05

1
Я удалил тег C ++, это чисто вопрос алгоритма, и, надеюсь, он не позволит несчастным последователям C ++ проголосовать против или проголосовать за закрытие.
Matthieu M.

Ответы:


43

Есть решение для динамического программирования. Мы начинаем с того, что 0 ключей может сделать нас 0 A. Затем мы выполняем итерацию iдо n, выполняя две вещи: один раз нажав A и нажав выбрать все + копировать, а затем вставить jвремя (на самом деле j-i-1ниже; обратите внимание на трюк здесь: содержимое все еще находится в буфере обмена, поэтому мы можем вставить его несколько раз без копирование каждый раз). Нам нужно рассмотреть только до 4 последовательных вставок, поскольку select, copy, paste x 5 эквивалентно выделению, копированию, вставке, выделению, копированию, вставке, а последнее лучше, поскольку оставляет нам больше в буфере обмена. Как только мы достигли nжелаемого результата.

Сложность может показаться O (N), но поскольку числа растут экспоненциально, на самом деле это O (N 2 ) из-за сложности умножения больших чисел. Ниже представлена ​​реализация Python. Расчет для N = 50 000 занимает около 0,5 секунды.

def max_chars(n):
  dp = [0] * (n+1)
  for i in xrange(n):
    dp[i+1] = max(dp[i+1], dp[i]+1) # press a
    for j in xrange(i+3, min(i+7, n+1)):
      dp[j] = max(dp[j], dp[i]*(j-i-1)) # press select all, copy, paste x (j-i-1)
  return dp[n]

В коде jпредставляет собой общее количество клавиш, нажатых после нашей новой последовательности нажатий клавиш. iНа этом этапе у нас уже есть нажатия клавиш, и 2 новых нажатия клавиш переходят в режим выбора и копирования. Таким образом, мы увеличиваем j-i-2время вставки . Поскольку вставка добавляет к существующей последовательности dp[i] A, нам нужно добавить 1создание j-i-1. Это объясняет j-i-1во второй-последней строке.

Вот некоторые результаты ( n=> количество пятерок):

  • 7 => 9
  • 8 => 12
  • 9 => 16
  • 10 => 20
  • 100 => 1391569403904
  • 1000 => 3268160001953743683783272702066311903448533894049486008426303248121757146615064636953144900245 174442911064952028008546304
  • 50 000 => очень большое количество!

Я согласен с @SB, что вы всегда должны высказывать свои предположения: мое заключается в том, что вам не нужно дважды вставлять, чтобы удвоить количество символов. Это дает ответ на 7, поэтому, если мое решение неверно, предположение должно быть правильным.

В случае , если кто - то удивляется , почему я не проверка последовательности вида Ctrl+ A, Ctrl+ C, A, Ctrl+ V: Конечный результат всегда будет таким же , как A, Ctrl+ A, Ctrl+ C, Ctrl+ , Vкоторую я бы рассмотреть.


Это n => resultили result => n? В любом случае, я считаю, что это неправильно. Мы можем ввести 9 As с 7 нажатиями клавиш. Если n => resultэто определенно неправильно. Количество As, которое вы можете ввести, не может быть меньше n.
IVlad 05

@IVlad Это n => result. Вы говорите: «Мы можем ввести 9 А с помощью 7 нажатий клавиш», и я получаю это. Прочтите «трюк», в котором я только что отредактировал.
moinudin 05

Это выглядит великолепно, за исключением того, что вопрос состоит в том, чтобы найти максимальное количество As для заданного количества нажатий клавиш, а не минимальное количество нажатий клавиш для получения данного количества As.
Эндрю Кларк

1
@marcog - ваши обозначения, по крайней мере, сбивают с толку, а в лучшем случае неверны. n- это сочетания клавиш, которые вам разрешено использовать. Вы должны вычислить, сколько вы можете набрать с помощью nнажатия клавиш. Так 7 => 7что смысла нет.
IVlad 05

1
Выглядит правильно, +1. Теперь давайте посмотрим, сможет ли кто-нибудь это понять O(n)или даже O(1):).
IVlad 05

41

Используя решение Marcog, я нашел образец, который начинается с n=16. Чтобы проиллюстрировать это, вот нажатия клавиш n=24до n=29, я заменил ^ A на S (выбрать), ^ C на C (копировать) и ^ V на P (вставить) для удобства чтения:

24: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4     = 1024
25: A,A,A,A,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *   3   *   3   *   3   *   3    = 1296
26: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *   3   *   3   *   3    = 1728
27: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,S,C,P,P
       4   *    4    *    4    *    4    *   3   *   3    = 2304
28: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P
       4   *    4    *    4    *    4    *    4    *   3    = 3072
29: A,A,A,A,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P,S,C,P,P,P
       4   *    4    *    4    *    4    *    4    *    4     = 4096

После начальных 4 As идеальный шаблон - выбрать, скопировать, вставить, вставить, вставить и повторить. Это умножит количество As на 4 каждые 5 нажатий клавиш. Если этот шаблон из 5 нажатий клавиш не может самостоятельно поглотить оставшиеся нажатия клавиш, некоторое количество из 4 шаблонов нажатий клавиш (SCPP) потребляют последние нажатия клавиш, заменяя SCPPP (или удаляя одну из вставок) по мере необходимости. Четыре комбинации нажатия клавиш умножают общую сумму на 3 каждые 4 нажатия.

Используя этот шаблон, вот некоторый код Python, который дает те же результаты, что и решение marcog, но редактирование O (1) : на самом деле это O (log n) из-за возведения в степень, спасибо IVlad за указание на это.

def max_chars(n):
  if n <= 15:
    return (0, 1, 2, 3, 4, 5, 6, 9, 12, 16, 20, 27, 36, 48, 64, 81)[n]
  e3 = (4 - n) % 5
  e4 = n // 5 - e3
  return 4 * (4 ** e4) * (3 ** e3)

Вычисление e3: в конце списка нажатий клавиш всегда есть от 0 до 4 шаблонов SCPP, поскольку n % 5 == 4их 4, n % 5 == 13, n % 5 == 22, n % 5 == 31 и n % 5 == 40. Это можно упростить до (4 - n) % 5.

Вычисление e4: общее количество паттернов увеличивается на 1 всякий раз n % 5 == 0, когда оказывается, что это число увеличивается ровно n / 5. Используя разделение этажей, мы можем получить общее количество шаблонов, общее количество для e4- это общее количество шаблонов за вычетом e3. Для тех, кто не знаком с Python, //это ориентированная на будущее нотация для разделения этажей.


1
Хороший! Протестировано и работает n=3000, так что наверное правильно. (Жаль, что у меня сегодня нет голосов: /)
moinudin 05

5
+1, очень красиво. Однако небольшая придирка: на самом деле это не так, O(1)поскольку возведение в степень не может быть выполнено за постоянное время. Это O(log n).
IVlad 05

2
На самом деле, последовательность «SCPPP» умножает количество символов только на три: первая вставка просто перезаписывает выделенный текст.
Ник Джонсон

4
@Nick Последняя строка в вопросе: «Последовательность Ctrl + A, Ctrl + V, Ctrl + C не перезапишет существующее выделение. Оно добавит скопированное выделение к выделенному».
moinudin 06

2
@marcog Да, я этого не заметил. Однако я не знаю ни одной ОС, которая ведет себя подобным образом.
Ник Джонсон

15

Вот как я подхожу к этому:

  • принять CtrlA= выбрать все
  • принять CtrlC= скопировать выделение
  • accept CtrlV= вставить скопированный выбор

учитывая некоторый текст, для его дублирования требуется 4 нажатия клавиш:

  • CtrlA выбрать все это
  • CtrlC скопировать это
  • CtrlV для вставки (это заклеит выделение - УКАЗЫВАЙТЕ СВОИ ПРЕДПОЛОЖЕНИЯ)
  • CtrlV снова вставить, что удваивает его.

Оттуда вы можете подумать о том, чтобы сделать 4 или 5 А, а затем повторить вышеописанное. Обратите внимание, что при выполнении ctrl + a, c, v, vбудет увеличиваться ваш текст экспоненциально по мере прохождения цикла. Если оставшихся штрихов <4, просто продолжайтеCtrlV

Ключ к собеседованию в таких местах, как Google, - это высказать свои предположения и передать свое мнение. они хотят знать, как вы решаете проблемы.


6
Хорошее замечание о технике собеседования: получение правильного ответа менее важно, чем четкое общение в конце!
fredley 05

2
Хороший ответ. Для алгоритма жадная ошибка « ACVV-VVVVVACVV-ACVV-V
вдвое»

5

Ее можно решить за O (1): как и в случае с числами Фибоначчи, существует формула для вычисления количества напечатанных As (и последовательности нажатий клавиш):


1) Мы можем упростить описание проблемы:

  • Имея только [A], [Ca] + [Cc], [Cv] и пустой буфер копирования-вставки

равно

  • имея только [Ca] + [Cc], [Cv] и «A» в буфере копирования-вставки.

2) Мы можем описать последовательность нажатий клавиш как строку из N символов из {'*', 'V', 'v'}, где 'v' означает [Cv], а '*' означает [Ca] и 'V 'означает [Копия]. Пример: "vvvv * Vvvvv * Vvvv"

Длина этой строки по-прежнему равна N.

Произведение длин Vv-слов в этой строке равно количеству произведенных As.


3) Учитывая фиксированную длину N для этой строки и фиксированное количество слов K, результат будет максимальным, если все слова имеют почти одинаковую длину. Их попарная разница не более ± 1.

Итак, какое оптимальное число K, если задано N?


4) Предположим, мы хотим увеличить количество слов, добавив одно слово длины L, тогда мы должны уменьшить L + 1 раз любое предыдущее слово на одну 'v'. Пример: «… * Vvvv * Vvvv * Vvvv * Vvvv» -> «… * Vvv * Vvv * Vvv * Vvv * Vvv»

Теперь, какова оптимальная длина слова L?

(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3

=> Оптимально L = 4.


5) Предположим, у нас есть достаточно большое N, чтобы сгенерировать строку с большим количеством слов длиной 4, но осталось несколько нажатий клавиш; как нам их использовать?

  • Если осталось 5 или больше: добавьте еще одно слово длиной 4.

  • Если осталось 0: Готово.

  • Если осталось 4: мы могли бы либо

    а) добавить одно слово длиной 3: 4 * 4 * 4 * 4 * 3 = 768.

    б) или увеличьте 4 слова до длины 5: 5 * 5 * 5 * 5 = 625. => Лучше добавить одно слово.

  • Если осталось 3: мы могли бы либо

    a) или добавьте одно слово длиной 3, изменив предыдущее слово с длины 4 на 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.

    б) увеличить 3 слова до длины 5: 5 * 5 * 5 = 125. => Лучше добавить одно слово.

  • Если осталось 2: мы могли бы либо

    a) или добавьте одно слово длиной 3, изменив предыдущие два слова с длины 4 на 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.

    б) увеличить 2 слова до длины 5: 5 * 5 = 25. => Лучше добавить одно слово.

  • Если остался 1: мы могли бы либо

    a) или добавьте одно слово длиной 3, изменив предыдущие три слова с длины 4 на 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.

    б) увеличить одно слово до длины 5: 4 * 4 * 5 = 80. => Лучше добавить одно слово.


6) А что, если у нас нет «достаточно большого N», чтобы использовать правила из 5)? По возможности мы должны придерживаться плана б)! Строки для маленьких N:

1: "v", 2: "vv", 3: "vvv", 4: "vvvv"

5: «vvvvv» → 5 (план б)

6: «vvvvvv» → 6 (план б)

7: «vvv * vvv» → 9 (план а)

8: «vvvv * vvv» → 12 (план а)

9: «vvvv * Vvvv» → 16

10: «vvvv * Vvvvv» → 20 (план б)

11: «vvv * vvv * vvv» → 29 (план а)

12: «vvvv * Vvv * Vvv» → 36 (план а)

13: «vvvv * Vvvv * Vvv» → 48 (план а)

14: «vvvv * Vvvv * Vvvv» → 64

15: «vvv * Vvv * Vvv * Vvv» → 81 (план а)


7) Каково оптимальное количество слов K в строке длины N?

Если N <7, то K = 1, иначе если 6 <N <11, то K = 2; в противном случае: K = ceil ((N + 1) / 5)

Написано на C / C ++ / Java: int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);

А если N> 10, то количество слов длиной 3 будет: K * 5-1-N. Таким образом, мы можем рассчитать количество напечатанных As:

Если N> 10, количество As будет: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}


Кажется, что это правильно, работает для примеров, приведенных в ответе @ Andrew, но ваш ответ также O (log N) вместо O (1), верно?
rsenna 06

Как это могло быть O (log N)? Математическая формула для вычисления количества As рассчитывается в O (1). Алгоритм печати нажатий клавиш - либо O (N), потому что нужно напечатать O (N) нажатий клавиш, либо O (1), если вы разрешите распечатать его как регулярное выражение.
comonad 07

Вычисление возведения в степень - O (log N), поскольку показатель степени на 4 увеличивается с N. Если вы распечатаете число As в факторизованной форме, это будет O (1).
Эндрю Кларк

Ах хорошо. Никогда не думал о том, чтобы вычислить число с помощью целочисленной арифметики. Меня интересует только формула или приближение с плавающей запятой. Но, конечно, чтобы можно было сравнить его с другими числами, его нужно рассчитать точно.
comonad

5

Использование CtrlA+ CtrlC+ CtrlVдает преимущество только после 4 'А'.

Поэтому я бы сделал что-то вроде этого (в псевдо-BASIC-коде, поскольку вы не указали правильный язык):

// We should not use the clipboard for the first four A's:
FOR I IN 1 TO MIN(N, 4)
    PRINT 'CLICK A'
NEXT
LET N1 = N - 4

// Generates the maximum number of pastes allowed:
FOR I IN 1 TO (N1 DIV 3) DO
    PRINT 'CTRL-A'
    PRINT 'CTRL-C'
    PRINT 'CTRL-V'
    LET N1 = N1 - 3
NEXT

// If we still have same keystrokes left, let's use them with simple CTRL-Vs
FOR I IN N1 TO N
    PRINT 'CTRL-V'
NEXT

редактировать

  1. Вернемся к использованию сингла CtrlVв основном цикле.
  2. Добавлены некоторые комментарии, объясняющие, что я пытаюсь здесь сделать.
  3. Исправлена ​​проблема с блоком «первые четыре A».

@SB: Я делаю CTRL-V только для ПОСЛЕДНИХ паст. Кстати, именно это вы и сказали в своем ответе. Это означает, что мы думаем одинаково, поэтому я не знаю, почему вы меня критикуете - а может, я что-то упускаю?
rsenna 05

1
Google никогда не указывает подходящий язык для записи, какой вы хотите.
Spooks

3

Чтобы удвоить количество As, нужно нажать 3 клавиши. Имеет смысл начинать удвоение только тогда, когда у вас уже напечатано 3 или более А. Вы хотите, чтобы последнее разрешенное нажатие клавиши было a, CtrlVчтобы удвоить максимальное число, которое вы можете, поэтому, чтобы выровнять его, мы будем заполнять любые дополнительные нажатия клавиш после первых трех As в начале с большим количеством As.

for (i = 3 + n%3; i>0 && n>0; n--, i--) {
    print("a");
}

for (; n>0; n = n-3) {
    print("ctrl-a");
    print("ctrl-c");
    print("ctrl-v");
}

Редактировать:

Это ужасно, я полностью забегал вперед и не считал несколько паст для каждой копии.

Изменить 2:

Я считаю, что вставка 3 раза является оптимальной, если для этого достаточно нажатий клавиш. За 5 нажатий клавиш вы умножаете свое число As на 4. Это лучше, чем умножение на 3 с помощью 4 нажатий клавиш, и лучше, чем умножение на 5 с помощью 6 нажатий клавиш. Я сравнил это, дав каждому методу одинаковое количество нажатий клавиш, достаточное для того, чтобы каждый из них закончил цикл одновременно (60), позволяя 3-умножителю делать 15 циклов, 4-умножителю делать 12 циклов, а 5- множитель сделать 10 циклов. 3 ^ 15 = 14 348 907, 4 ^ 12 = 16 777 216 и 5 ^ 10 = 9 765 625. Если осталось только 4 нажатия клавиши, сделать 3-множитель лучше, чем вставлять еще 4 раза, по сути, превратив предыдущие 4 множителя в 8-множитель. Если осталось только 3 нажатия клавиши, лучше всего использовать множитель 2.


2

Предположим, у вас есть x символов в буфере обмена и x символов в текстовой области; назовем это «состояние x».

Давайте несколько раз нажмем «Вставить» (я m-1для удобства обозначил это как ), затем «Выбрать все» и «Копировать»; после этой последовательности мы попадаем в «состояние m * x». Здесь мы потратили в общей сложности m + 1 нажатие клавиш. Так что асимптотический рост (по крайней мере) примерно такой f^n, где f = m^(1/(m+1)). Я считаю, что это максимально возможный асимптотический рост, хотя я не могу это доказать (пока).

Попытка различных значений m показывает, что максимум для f достигается при m=4.

Воспользуемся следующим алгоритмом:

Press A a few times
Press Select-all
Press Copy
Repeat a few times:
    Press Paste
    Press Paste
    Press Paste
    Press Select-all
    Press Copy
While any keystrokes left:
    Press Paste

(не уверен, что это оптимальный вариант).

Количество нажатий A в начале равно 3: если вы нажмете его 4 раза, вы упустите возможность удвоить количество A еще тремя нажатиями клавиш.

Количество нажатий «Вставить» в конце не более 5: если у вас осталось 6 или более нажатий клавиш, вы можете вместо этого использовать «Вставить», «Вставить», «Вставить», «Выбрать все», «Копировать», «Вставить».

Итак, получаем следующий алгоритм:

If (less than 6 keystrokes - special case)
    While (any keystrokes left)
        A
Else
    First 5 keystrokes: A, A, A, Select-all, Copy
    While (more than 5 keystrokes left)
        Paste, Paste, Paste, Select-all, Copy
    While (any keystrokes left)
        Paste

(не уверен, что это оптимальный вариант). Количество символов после выполнения примерно такое:

3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5).

Примеры значений: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...


2

Далее используется второе редактирование OP, при котором вставка не заменяет существующий текст.

Обратите внимание на несколько вещей:

  • ^ A и ^ C можно рассматривать как одно действие, требующее двух нажатий клавиш, поскольку никогда не имеет смысла выполнять их по отдельности. На самом деле, мы можем заменить все экземпляры ^ А ^ С с ^ K ^ V, где ^ K является один ключ «вырезать» операции (давайте сокращайте его X). Мы увидим, что иметь дело с ^ K намного приятнее, чем с ^ A ^ C с двумя затратами.
  • Предположим, что в буфере обмена начинается буква «А». Тогда ^ V (сокращенно Y) строго превосходит A, и мы можем исключить последний из всех соображений. (В реальной задаче, если буфер обмена начинается пустым, в дальнейшем мы просто заменим Y на A вместо ^ V до первого X.)

Таким образом, каждую разумную последовательность нажатий клавиш можно интерпретировать как группу Y, разделенных X, например YYYXYXYYXY. Обозначим через V (s) количество «А», произведенных последовательностью s. Тогда V (nXm) = V (n) * V (m), потому что X по существу заменяет каждый Y в m на V (n) 'A.

Таким образом, проблема копирования и вставки изоморфна следующей проблеме: «используя m + 1 чисел, сумма которых равна Nm, максимизируйте их произведение». Например, когда N = 6, ответ будет m = 1 и числа (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (или V (YYYXYY) = V (AAA ^ A ^ C ^ V).)

Мы можем сделать несколько наблюдений:

Для фиксированного значения mвыбираются числа ceil( (N-m)/(m+1) )и floor( (N-m)/(m+1) )(в какой бы комбинации ни вычислялась сумма; в частности, вам понадобятся (N-m) % (m+1) ceilsи остальные floors). Это потому, что, a < b, (a+1)*(b-1) >= a*b.

К сожалению, я не вижу простого способа определить значение m. Если бы это было мое интервью, я бы предложил два решения на этом этапе:

Вариант 1. Перебрать все возможное m. n log nРешение O ( ).

Код на C ++:

long long ipow(int a, int b)
{
  long long val=1;
  long long mul=a;

  while(b>0)
    {
      if(b%2)
    val *= mul;
      mul *= mul;
      b/=2;
    }
  return val;
}

long long trym(int N, int m)
{
  int floor = (N-m)/(m+1);
  int ceil = 1+floor;
  int numceils = (N-m)%(m+1);
  return ipow(floor, m+1-numceils) * ipow(ceil, numceils);
}

long long maxAs(int N)
{
  long long maxval=0;
  for(int m=0; m<N; m++)
    {
      maxval = std::max(maxval, trym(N,m));
    }
  return maxval;
}

Вариант 2. Дать mвозможность получить нецелые значения и найти его оптимальное значение, взяв производную [(N-m)/(m+1)]^mпо mи решив ее корень. Аналитического решения нет, но корень можно найти, например, методом Ньютона. Затем используйте пол и потолок этого корня в качестве значения mи выберите тот, который лучше.


0
public int dp(int n) 
{
    int arr[] = new int[n];
    for (int i = 0; i < n; i++)
        arr[i] = i + 1;
    for (int i = 2; i < n - 3; i++) 
    {
        int numchars = arr[i] * 2;
        int j = i + 3;
        arr[j] = Math.max(arr[j], numchars);
        while (j < n - 1) 
        {
            numchars = numchars + arr[i];
            arr[++j] = Math.max(arr[j], numchars);
        }
    }
    return arr[n - 1];
}

0

Вот мой подход и решение с кодом ниже.

Подходить:

Можно выполнить три различные операции.

  1. Нажатие клавиши A - выводит один символ 'A'
  2. Нажатие клавиши (Ctrl-A) + (Ctrl-C) - ничего по существу не выводит. Эти два нажатия клавиш можно объединить в одну операцию, потому что каждое из этих нажатий клавиш по отдельности не имеет смысла. Кроме того, это нажатие клавиши настраивает вывод для следующей операции вставки.
  3. Нажатие клавиши (Ctrl-V) - вывод для этого нажатия действительно зависит от предыдущей (второй) операции, и, следовательно, нам нужно будет учесть это в нашем коде.

Теперь, учитывая три различных операции и их соответствующие выходы, мы должны выполнить все перестановки этих операций.


Предположение:

В некоторой версии этой проблемы говорится, что последовательность нажатий клавиш Ctrl + A -> Ctrl + C -> Ctrl + V перезаписывает выделенное выделение. Чтобы учесть это предположение, нужно добавить только одну строку кода в решение ниже, где для печатаемой переменной в случае 2 установлено значение 0.

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

Для этого решения

Приведенный ниже код напечатает пару последовательностей, и последняя последовательность будет правильным ответом для любого заданного N. например, для N = 11 это будет правильная последовательность.

При предположении

A, A, A, A, A, C, S, V, V, V, V,: 20:

Без предположения

A, A, A, C, S, V, V, C, S, V, V,: 27:

Я решил сохранить предположение для этого решения.


Легенда нажатия клавиш:

'А' - А

'C' - Ctrl + A

'S' - Ctrl + C

'V' - Ctrl + V


Код:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void maxAprinted(int count, int maxKeys, int op, int printed, int pOutput, int *maxPrinted, char *seqArray)
{
    if(count > maxKeys)
        return;

    if(count == maxKeys)
    {
        if((*maxPrinted) < printed)
        {
            //new sequence found which is an improvement over last sequence
            (*maxPrinted) = printed;

            printf("\n");
            int i;
            for(i=0; i<maxKeys; i++)
                printf(" %c,",seqArray[i]);
        }

        return;
    }

    switch(op)
    {
        case 1:
        //A keystroke
            printed++;

            seqArray[count] = 'A';
            count++;
            break;

        case 2:
        //Ctrl-A and then Ctrl-C
            if((count+2) < maxKeys)
            {
                pOutput = printed;

                //comment the below statement to NOT factor 
                //in the assumption described above
                printed = 0;    
            }

            seqArray[count] = 'C';
            count++;
            seqArray[count] = 'S';
            count++;
            break;

        case 3:
        //Ctrl-V
            printed = printed + pOutput;

            seqArray[count] = 'V';
            count++;
            break;
    }

    maxAprinted(count, maxKeys, 1, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 2, printed, pOutput, maxPrinted, seqArray);
    maxAprinted(count, maxKeys, 3, printed, pOutput, maxPrinted, seqArray);    
}

int main()
{
    const int keyStrokes = 11;

    //this array stores the sequence of keystrokes
    char *sequence;
    sequence = (char*)malloc(sizeof(char)*(keyStrokes + 1));

    //stores the max count for As printed for a sqeuence
    //updated in the recursive call.
    int printedAs = 0;

    maxAprinted(0, keyStrokes,  1, 0, 0, &printedAs, sequence);

    printf(" :%d:", printedAs);

    return 0;
}    

0

Используя приемы, упомянутые в ответах выше, математически решение можно объяснить одним уравнением следующим образом:

4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. где [] - наибольший целочисленный множитель


0

Существует компромисс между печатью мА вручную, а затем использованием Ctrl+ A, Ctrl+ Cи Нм-2 Ctrl+ V. Лучшее решение - посередине. Если максимальное количество нажатий клавиш = 10, лучшим решением будет ввод 5 или 4 А.

попробуйте использовать это. Посмотрите на это http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ и, возможно, немного оптимизируйте поиск результатов примерно в середине точка.


0

Вот мое решение с динамическим программированием без вложенного цикла, которое также выводит фактические символы, которые вам нужно ввести:

N = 52

count = [0] * N
res = [[]] * N
clipboard = [0] * N

def maybe_update(i, new_count, new_res, new_clipboard):
  if new_count > count[i] or (
      new_count == count[i] and new_clipboard > clipboard[i]):
    count[i] = new_count
    res[i] = new_res
    clipboard[i] = new_clipboard

for i in range(1, N):
  # First option: type 'A'.
  # Using list concatenation for 'res' to avoid O(n^2) string concatenation.
  maybe_update(i, count[i - 1] + 1, res[i - 1] + ['A'], clipboard[i - 1])

  # Second option: type 'CTRL+V'.
  maybe_update(i, count[i - 1] + clipboard[i - 1],  res[i - 1] + ['v'],
               clipboard[i - 1])

  # Third option: type 'CTRL+A, CTRL+C, CTRL+V'.
  # Assumption: CTRL+V always appends.
  if i >= 3:
    maybe_update(i, 2 * count[i - 3],  res[i - 3] + ['acv'], count[i - 3])

for i in range(N):
  print '%2d %7d %6d %-52s' % (i, count[i], clipboard[i], ''.join(res[i]))

Это результат ('a' означает 'CTRL + A' и т. Д.)

 0       0      0                                                     
 1       1      0 A                                                   
 2       2      0 AA                                                  
 3       3      0 AAA                                                 
 4       4      0 AAAA                                                
 5       5      0 AAAAA                                               
 6       6      3 AAAacv                                              
 7       9      3 AAAacvv                                             
 8      12      3 AAAacvvv                                            
 9      15      3 AAAacvvvv                                           
10      18      9 AAAacvvacv                                          
11      27      9 AAAacvvacvv                                         
12      36      9 AAAacvvacvvv                                        
13      45      9 AAAacvvacvvvv                                       
14      54     27 AAAacvvacvvacv                                      
15      81     27 AAAacvvacvvacvv                                     
16     108     27 AAAacvvacvvacvvv                                    
17     135     27 AAAacvvacvvacvvvv                                   
18     162     81 AAAacvvacvvacvvacv                                  
19     243     81 AAAacvvacvvacvvacvv                                 
20     324     81 AAAacvvacvvacvvacvvv                                
21     405     81 AAAacvvacvvacvvacvvvv                               
22     486    243 AAAacvvacvvacvvacvvacv                              
23     729    243 AAAacvvacvvacvvacvvacvv                             
24     972    243 AAAacvvacvvacvvacvvacvvv                            
25    1215    243 AAAacvvacvvacvvacvvacvvvv                           
26    1458    729 AAAacvvacvvacvvacvvacvvacv                          
27    2187    729 AAAacvvacvvacvvacvvacvvacvv                         
28    2916    729 AAAacvvacvvacvvacvvacvvacvvv                        
29    3645    729 AAAacvvacvvacvvacvvacvvacvvvv                       
30    4374   2187 AAAacvvacvvacvvacvvacvvacvvacv                      
31    6561   2187 AAAacvvacvvacvvacvvacvvacvvacvv                     
32    8748   2187 AAAacvvacvvacvvacvvacvvacvvacvvv                    
33   10935   2187 AAAacvvacvvacvvacvvacvvacvvacvvvv                   
34   13122   6561 AAAacvvacvvacvvacvvacvvacvvacvvacv                  
35   19683   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvv                 
36   26244   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvv                
37   32805   6561 AAAacvvacvvacvvacvvacvvacvvacvvacvvvv               
38   39366  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacv              
39   59049  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvv             
40   78732  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvv            
41   98415  19683 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvvv           
42  118098  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacv          
43  177147  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv         
44  236196  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv        
45  295245  59049 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv       
46  354294 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv      
47  531441 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv     
48  708588 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvv    
49  885735 177147 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvvv   
50 1062882 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacv  
51 1594323 531441 AAAacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvvacvv 

0

Если разрешено N нажатий клавиш, результатом будет N-3.

А -> Н-3

CTRL+ A-> Выбор этих N символов: +1

CTRL+ C-> Копирование этих N символов: +1

Ctrl+ V-> Вставка N символов. : +1 то есть (поскольку мы выбрали все символы с помощью CTRL+ A) Замена этих существующих символов N-3 на скопированные символы N-3 (что заменяет те же символы), и результат будет N-3.


Добро пожаловать в StackOverflow! Узнайте, как добавить форматирование содержимого и, возможно, использовать фактический символ стрелки . Это улучшит читаемость вашего ответа!
M. Mimpen
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.