Zadanie
Vladko sa veľmi rád hrá počítačové hry. Naposledy si cez letné zľavy v intergalatickom obchode Para™ kúpil vesmírnu plošinovku. Narazil však na náročný level, v ktorom sa nachádza niekoľko políčok vedľa seba, na niektorých sa nachádzajú plošinky. Vladko začína úplne vľavo, cieľ levelu je úplne vpravo. Hýbať sa môže iba doprava. Vždy, keď sa postaví na políčko s plošinkou, môže sa posunúť doprava a plošinka sa za ním rozpadne. Ak sa postaví na políčko bez plošinky, spadne do lávy (musí začať znovu) a na políčku sa objaví nová plošinka.
Úloha
Vladko chce zistiť, na koľko najmenej pokusov vie tento level dokončiť.
Formát vstupu
V prvom riadku vstupu je číslo \(n\) (\(1 \leq n \leq 60\)), ktoré určuje počet políčok vedľa seba.
Nasleduje jeden riadok, na ktorom je medzerou oddelených \(n\) čísiel \(0\) alebo \(1\), ktoré určujú, či sa na danom políčku nachádza plošinka, alebo nie.
Sada | 1, 2 | 3, 4 | 5, 6 | 7, 8 |
---|---|---|---|---|
\(1 \leq n \leq\) | \(10\) | \(30\) | \(60\) | \(60\) |
Formát výstupu
Vypíšte jeden riadok s najmenším počtom pokusov, s ktorým sa dá tento
level vyhrať. Pozor, výstupné číslo sa ti nemusí zmesiť do premennej
typu int
v C++.
Príklad
Input:
3
0 0 1
Output:
3
Potrebuje 3 pokusy: 0 0 1
→ 1 0 1
→
0 1 1
→ 1 1 1
Simulácia
Priamočiarým riešením by mohlo byť si Vladkove hranie odsimulovať. Prechádzať po políčkach zľava doprava, vždy zmeniť stav plošinky a po postavení sa na políčko bez plošinky, vrátiť sa na začiatok. Počas tohto si budeme počítať, koľko krokov sme spravili. Toto budeme opakovať dovtedy, kým sa Vladko nedostane na koniec.
Toto riešenie funguje, avšak je pomerne pomalé.
Potrebujeme to simulovať?
Skúsme sa pozrieť na niektoré hry. Ak Vladkov level začína v stave
0 0 0
, po prvom prejdení skončí v stave 1 0 0
,
potom 0 1 0
, 1 1 0
, 0 0 1
,
1 0 1
, 0 1 1
a skončí v 1 1 1
.
Vladko tento level dokončí po \(7\)-ich
pokusoch.
Môžeme si všimnúť, že ak by sme level mali nakreslený opačne, tak
postupnosť 0 0 0
, 0 0 1
, 0 1 0
…
vyzerá presne ako postupnosť binárnych čísiel od \(0\) do \(7\). Teraz si potrebujeme uvedomiť, že
každý level, ktorý sa skladá iba z políčok bez plošiniek sa správa
rovnako, a teda ho vieme reprezentovať ako postupnosť binárnych čísiel
od \(0\) po \(x\). Následne potrebujeme zistiť, aké je to
\(x\) pre daný počet políčok. Ak máme v
leveli \(n\) políčok, aké najväčšie
binárne číslo v ňom vieme zobraziť? To bude \(n\) jednotiek. Ak \(n\) binárnych jednotiek chceme premeniť na
číslo v desiatkovej sústave, dostaneme \(2^0 +
2^1 + \dots + 2^{n-1}\). Alternatívne, vieme, že ak máme \(n\) binárnych jednotiek, tak číslo o jedna
väčšie bude jednotka a \(n\) núl, čiže
\(2^n\) v desiatkovej sústave. Potom
naše pôvodné číslo bude \(2^n-1\).
Čo ale, ak nezačíname so samými nulami? Vtedy môžeme počiatočný stav vyjadrený ako binárne číslo odpočítať od celkového počtu pokusov, keby všetky políčka boli nulové.
Alternatívne môžeme počiatočný stav ako binárne číslo znegovať
(0 1 0
-> 1 0 1
) a premeniť do desiatkovej
sústavy, čím dostaneme počet pokusov.
Časová aj pamäťová zložitosť takéhoto riešenia je \(O(n)\). Technicky si nemusíme pamätať celý vstup, ale spracovávať ho postupne, vtedy by sme vedeli dostať pamäťovú zložitosť aj \(O(1)\).
= int(input())
n = list(map(bool, map(int, input().split())))
states
= 0
flips
for i, s in enumerate(states):
if not s:
+= 2**i
flips
print(flips)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
int n;
>> n;
cin = 0;
ll helper = 1;
ll power
char c;
for (int i = 0; i < n; i++){
>> c;
cin += power*(c - '0');
helper *= 2;
power }
<< (power - helper - 1) << "\n";
cout }
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ť.