Максимальна кількість символів за допомогою натискань клавіш A, Ctrl + A, Ctrl + C і Ctrl + V


106

Це питання інтерв'ю від google. Я не в змозі вирішити це самостійно. Може хтось пролити світло?

Напишіть програму для друку послідовності натискань клавіш, щоб вона генерувала максимальну кількість символів "A". Вам дозволяється використовувати тільки 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, один Ctrl+ A, один Ctrl+ Cі y Ctrl+ V, ми можемо генерувати максимальне ((N-1) / 2) 2 число A. Для деякого N> M, то краще використовувати , як багато Ctrl+ A«s, Ctrl+ Cі Ctrl+ Vпослідовності , як це подвоює кількість в.

Послідовність Ctrl+ A, Ctrl+ V, Ctrl+ Cне замінить існуючий вибір. Він додасть скопійований вибір до вибраного.


У багатьох текстових редакторах ^Aзазвичай "виділити все", ^Cє "копіювати", ^Vє "вставити". Це дає вам ідею?
Микола Фетисов

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

А, це 7 натискань клавіш.
Джон Дайблінг

@John "Усі символи CTRL + вважаються одним натисканням клавіші, тому CTRL + A - одним натисканням клавіші."
Фредлі

1
Я видалив тег C ++, це суто питання щодо алгоритму, і, сподіваємось, це запобіжить невдоволеним підписникам C ++, щоб не допустити / проголосувати за закриття.
Матьє М.

Відповіді:


43

Є динамічне рішення програмування. Ми починаємо, знаючи, що 0 клавіш можуть зробити нас 0 А. Потім ми повторюємо iдо n, робимо дві речі: натискання клавіші A один раз та натискання клавіші "Вибрати всі +", а потім - jчасові вставки (фактично j-i-1нижче; зверніть увагу на трюк: вміст все ще знаходиться в буфері обміну, тому ми можемо вставити його кілька разів без копіювання кожного разу). Ми маємо розглянути лише до 4 послідовних паст, оскільки виділити, скопіювати, вставити х 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's, нам потрібно додати 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 Як із 7 натискань клавіш. Якщо це n => resultточно не так. Кількість типу "Введення" не може бути меншою за n.
IVlad

@IVlad It n => result. Ви кажете "Ми можемо набрати 9 Як і 7 натискань клавіш", це те, що я отримую. Прочитайте "трюк", який я щойно відредагував.
moinudin

Це виглядає чудово, за винятком того, що питання полягає у пошуку максимальної кількості As для заданої кількості натискань клавіш, а не мінімальної кількості натискань клавіш для отримання заданої кількості As.
Ендрю Кларк

1
@marcog - ваші позначення принаймні заплутані і, максимум, неправильні. n- це натискання клавіш, які ви можете використовувати. Ви повинні обчислити кількість Скільки набираєте nклавіш. Тому 7 => 7немає сенсу.
IVlad

1
Виглядає правильно, + 1. Тепер давайте подивимось, чи хтось може це звести O(n)або навіть O(1):).
IVlad

41

Використовуючи розчин Маркога, я знайшов шаблон, який починається з 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 (або видаляючи одну з паст) за необхідності. 4 схеми натискання клавіш множать загальну кількість на 3 кожні 4 натискання клавіш.

Використовуючи цей шаблон тут деякі Python код , який отримує ті ж результати , як рішення marcog, але це O (1) редагувати : Це на самому справі O (журнал 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 == 1є 3, n % 5 == 2є 2, n % 5 == 3є 1 і n % 5 == 4є 0. Це можна спростити до (4 - n) % 5.

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


1
Хороший! Випробуваний і він працює n=3000, тому, мабуть, правильно. (Шкода, що сьогодні я не
голосую

5
+1, дуже приємно. Незначна ніпеля, проте: це насправді не так, O(1)як експоненцію неможливо зробити за постійний час. Це O(log n).
IVlad

2
Насправді послідовність "SCPPP" лише помножить кількість символів на три: перша вставка просто перезапише обраний текст.
Нік Джонсон

4
@Nick Останній рядок у запитанні: "Послідовність Ctrl + A, Ctrl + V, Ctrl + C не замінить існуючий вибір. Він додасть скопійований вибір до вибраного."
moinudin

2
@marcog Так, я цього не помічав. Я не знаю жодної ОС, яка веде себе таким чином.
Нік Джонсон

15

Ось як я підійшов би до цього:

  • припустити CtrlA = вибрати всіх
  • припустити CtrlC = вибір копії
  • припустити CtrlV = вставити скопійований вибір

з урахуванням тексту, для його копіювання потрібно 4 натискання клавіш:

  • CtrlA щоб вибрати це все
  • CtrlC скопіювати його
  • CtrlV щоб вставити (це вставить на вибір - СТАНУЙТЕ ВАШІ ПИТАННЯ)
  • CtrlV знову вставити, що подвоює його.

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

Ключовим словом для інтерв'ю @ таких місць, як Google, є висловлення ваших припущень та передача думок. вони хочуть знати, як ви вирішуєте проблеми.


6
Гарний момент щодо техніки інтерв'ю, отримання правильної відповіді менш важливий, ніж чітке спілкування в кінці кінців!
fredley

2
Хороша відповідь. Для алгоритму жадібна помилка на два: ACVV-VVVVVмножиться на 7, ACVV-ACVV-Vпомножує на 6. Тож Ctrl-V для решти штрихів <6 замість 4.
Марсель Джекверт

5

Це можна вирішити в O (1): Як і у числах Фібоначчі, існує формула для обчислення кількості надрукованих As (та послідовності натискань клавіш):


1) Ми можемо спростити опис проблеми:

  • Маючи лише [A], [Ca] + [Cc], [Cv] та порожній буфер copy-paste-буфера

дорівнює

  • маючи лише [Ca] + [Cc], [Cv] і "A" в буфері копіювання-вставки.

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

Довжина цього рядка все ще дорівнює Н.

Добуток довжин 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: ми могли б і будь-яке

    а) або додайте одне слово довжиною 3, відрегулювавши попереднє слово від довжини 4 до 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.

    б) збільшити 3 слова до довжини 5: 5 * 5 * 5 = 125. => Додавання одного слова краще.

  • Якщо залишилося 2: ми могли б і будь-яке

    а) або додайте одне слово довжиною 3, відрегулювавши попереднє два слова від довжини 4 до 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.

    б) збільшити 2 слова до довжини 5: 5 * 5 = 25. => Додавання одного слова краще.

  • Якщо залишилося 1: ми могли б і будь-яке

    а) або додайте одне слово довжиною 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 (план b)

6: "vvvvvv" → 6 (план b)

7: "vvv * Vvv" → 9 (план a)

8: "vvvv * Vvv" → 12 (план а)

9: "vvvv * Vvvv" → 16

10: "vvvv * Vvvvv" → 20 (план b)

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 (план a)


7) Тепер, яка оптимальна кількість K слів у рядку довжиною N?

Якщо N <7, то K = 1 інше, якщо 6 <N <11, то K = 2; інакше: K = стеля ((N + 1) / 5)

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

А якщо N> 10, то кількість слів довжиною 3 складе: K * 5-1-N. За допомогою цього ми можемо обчислити кількість надрукованих як:

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


Здається, це правильно, працює на прикладах, наведених у відповіді @ Андрія, але ваша відповідь також O (log N) замість O (1), правда?
rsenna

Як це могло бути O (лог N)? Математична формула для обчислення числа As обчислюється в O (1). Алгоритм для друку натискань клавіш або O (N), оскільки для друку є O (N) натискань клавіш, або O (1), якщо ви дозволяєте друкувати його як регулярний вираз.
comonad

Обчислення експоненції дорівнює 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. Виправлена ​​проблема з блоком "перші чотири А".

@SB: Я роблю CTRL-V лише для ОСТАННІХ паст. Що саме, до речі, ви сказали у своїй відповіді. Що означає, що ми думаємо подібне, тому я не знаю, чому ти мене критикуєш - чи, може, я щось пропускаю?
rsenna

1
google ніколи не вказує належної мови, якою потрібно писати.
Розмовляє

3

Для подвоєння вашої кількості As потрібно 3 натискання клавіш. Починати подвоєння має сенс лише тоді, коли у вас є 3 і більше, як уже надруковано. Ви хочете, щоб ваш останній дозволений натискання клавіші був a, CtrlVщоб переконатися, що ви подвоюєте найбільше число, яке ви можете, тому для того, щоб вирівняти його, ми заповнимо будь-які додаткові натискання клавіш після перших трьох. Як на початку, ще більше 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 символів у текстовій області; назвемо це "станом х".

Давайте кілька разів натискаємо «Вставити» (позначаю це 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 на 3 більше натискання клавіш.

Кількість натискань на кнопку "Вставити в кінці" не більше 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

Далі використовується другий редагувати оп, що склеювання робить НЕ замінює існуючий текст.

Зауважте кілька речей:

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

Кожна розумна послідовність натискання клавіш може бути інтерпретована як група Ys, розділених Xs, наприклад YYYXYXYYXY. Позначимо через V (s) число 'A', отримане послідовністю s. Тоді V (nXm) = V (n) * V (m), оскільки X по суті замінює кожну Y в m на V (n) 'A's.

Проблема копіювання-вставки, таким чином, ізоморфна наступній проблемі: "використовуючи 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. Рішення O ( n log n).

Код 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 = 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

Існує компроміс між друком mA вручну, потім використанням Ctrl+ A, Ctrl+ Cта Nm-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.

А -> N-3

CTRL+A -> Вибір цих N символів: +1

CTRL+C -> Копіювання цих N символів: +1

Ctrl+ V-> Вставка N символів. : +1, тобто (Оскільки ми вибрали цілі символи за допомогою CTRL+ A) Заміна цих існуючих символів N-3 скопійованими символами N-3 (що переосмислює ті самі символи), і результат N-3.


Ласкаво просимо до StackOverflow! Дізнайтеся, як додати форматування вмісту та, можливо, використовувати фактичний символ стрілки . Це покращить читабельність вашої відповіді!
М. Мімпен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.