Zadanie
Náš kamarát Miško z planéty “Flexi 128” chcel podporiť vymýšľanie tohto kola, a preto s nami chcel zdieľať jeho knižnicu hier na intergalaktickom obchode Para™. Nevedel nám však poslať jeho heslo, kvôli tej hlúpej intergalatickej pošte! Našťastie, jeho heslo má iba jediný znak v kódovacej sústave UTF-4096, čo je štandardizované kódovanie v širokej galaxii. A máme iného kamaráta, ktorý si pamätá ako vzniklo - je to predsa iba počet krokov, ktoré potrebuje na zadanie pin kódu na svojich smart StarFruit™ hodinkách. Celkom ľahko sa používajú - stačí iba otáčat vonkajším okruhom, ako trezorom a vždy, keď je na čísle, ktoré by chcel zadať, stlačí displej. Jediný problem je, že jeho pin kód vie byť veľmi dlhý. Jazyk C** alebo Cobra sa už takýmito ľahkými problémami nezaoberajú. Pomôžte nám!
Úloha
Naprogramujte program, ktorý zistí minimálny počet krokov, ktoré potrebujeme na zadanie Miškovho pin kódu na jeho hodinky.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
---|
Takto vyzerá pásik na hodinkách. Treba si uvedomiť, že sa vieme pohnúť z 0 na 1 a naopak. Každý pohyb doľava či doprava sa ráta ako jeden krok, a taktiež musíme zarátať stlačenie displeja ako jeden krok. Treba ešte spomenúť, že začíname “ukazovátkom” na 1, a nemusíme sa vrátiť na pôvodnú pozíciu po stlačení.
Formát vstupu
V prvom riadku vstupu je reťazec dĺžky \(n\) (\(1 \leq n \leq 10^6\)) - Miškov pin kód. Jeho pin kód bude obsahovať iba znaky od 0 po 9.
Pre jednotlivé sady platia takéto obmedzenia:
Sada | 1 | 2 | 3 | 4 |
---|---|---|---|---|
\(1 \leq n \leq\) | \(20\) | \(1000\) | \(10^4\) | \(10^{6}\) |
Formát výstupu
Vypíšte na jeden riadok minimálny počet krokov, ktoré Miško potrebuje na zadanie pin kódu - teda heslo od jeho Para™ účtu.
Príklad
Input:
820
Output:
12
Naša cesta je nasledovná 1-8-klik-2-klik-0-klik Treba si uvedomiť že cesta z 1-8 ide 1=>0=>9=>8, takže 3 kroky
Input:
8573
Output:
16
Ako
najjednoduchšie riešenie je si sitúaciu odsimulovať. Spraviť si pole
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
a pamätať si pozíciu, na
ktorej sa nachádzame. Túto pozíciu meníme a pre každé číslo v pin-e si
pomocou cyklu cez pole zistíme, ktorá strana je bližšie a na tú stranu
sa vydáme. Pri takomto počítaní nemôžeme zabudnúť, že pole je ako keby
tvaru kruhu a preto musíme myslieť na pozície na krajoch (1 -> 0 a 0
-> 1). Toto však nie je úplne najlepšie riešenie.
Problém si chceme simulovať, ale nechceme manuálne pohybovať ukazovátkom. Vlastne, z každého bodu máme dve cesty kadiaľ sa vieme vybrať. Buď doľava alebo doprava. Minimum pohybov potrebných na napísanie pinu dostaneme vtedy, keď si vždy vyberieme tú kratšiu cestu. Ešte však treba vymyslieť logiku za tým, koľko krokov potrebujeme na to, aby sme sa dostali na číslo z nejakej pozície.
Stále si potrebujeme pamätať našu pozíciu, no nejdeme krok po kroku, ale vypočítame si počet krokov, ktoré potrebujeme. V našom cykle pozíciu potom vždy updatujeme iba na miesto, kam sa chceme presunúť.
Treba si uvedomiť že k počtu krokov môžeme ihneď pripočítať dĺžku pin kódu, keďže určite budeme musieť každé číslo stlačiť.
Ak sa chceme dostať z čísla 5 na 6 alebo 6 na 5 je to vlastne \(\text{abs}(6-5)\) alebo \(\text{abs}(5-6)\), čo je rovnaké číslo. Musíme však rátať aj s tým, že cesta druhou stranou vie niekedy byť rýchlejšia. Cestu druhou stranou dostaneme keď od celkového počtu políčok odčítame vzdialenosť, ktorú by sme prešli ak by sme nepoužili cestu z 1 na 0. Teda pre nás je to \(10 - \text{abs}(5-6)\), čo nám dá výsledok 9, čo je naozaj počet krokov, keby putujeme druhou stranou. Vzorec na výpočet najkratšej vzdialenosti z pozície \(i\) na pozíciu \(x\) bude teda vyzerať takto: \(\text{min}(\text{abs}(x-i), 10 - \text{abs}(x-i))\)
Menšiu z týchto dvoch možností (ísť doľava alebo doprava) pripočítame k počtu krokov a opakujeme pre všetky čísla v pin-e. Keď prejdeme všetkými číslami v pin-e, vypíšeme celkový počet krokov.
def main():
= input()
code = 0
res = 1
prev += len(code) # pridame pocet znakov, kedze aj zadat znak stoji 1
res for c in code:
= int(c)
num if num == 0:
= 10 # toto aby 0 bola ako keby na desiatej pozicii
num # pridame minimalnu vzdialenost medzi cislami
+= min(abs(num - prev), 10 - abs(num - prev)) # 10-abs(num-prev) je vzdialenost ak pouzijeme cyklus
res = num # aktualizujeme nasu poziciu
prev print(res)
if __name__ == "__main__":
# je dobre pouzit main, python potom bezi rychlejsie main()
#include <bits/stdc++.h>
using namespace std;
int main(){
::sync_with_stdio(false);
ios.tie(0);
cin.tie(0);
cout;
string code>> code;
cin long long res = 0;
int prev = 1;
+=code.size(); // pridame pocet znakov, kedze aj zadat znak stoji 1
resfor(char c : code){
int num = c - '0'; // prevedieme znak na cislo
if(num == 0){
= 10; // toto aby 0 bola ako keby na desiatej pozicii
num }
+= min(abs(num-prev), 10-abs(num-prev)); // pridame minimalnu vzdialenost medzi cislami
res //10-abs(num-prev) je vzdialenost ak pouzijeme cyklus
= num; // aktualizujeme nasu poziciu
prev }
std::cout << res << std::endl; //vypiseme vysledok a newline!!
}
Diskusia
Tu môžte voľne diskutovať o riešení, deliť sa o svoje kusy kódu a podobne.
Pre pridávanie komentárov sa musíš prihlásiť.