Knight's Tour – obilazak konja (backtracking rešenje)

Zadatak:
Napiši program koji pronalazi obilazak konja (Knight's Tour) na šahovskoj tabli dimenzije n × n. Konj treba da obiđe sva polja table tako da svako polje bude posećeno tačno jednom, prateći pravila kretanja konja u šahu.

Obilazak može biti:

  • otvoren – poslednje polje ne napada prvo;
  • zatvoren – poslednje polje napada prvo, čineći ciklus.
Ovaj primer traži bilo kakav validan obilazak koristeći backtracking.

Ulaz: Sa standardnog ulaza unosi se broj n (5 ≤ n ≤ 10).
Izlaz: Ako rešenje postoji, ispisuje se matrica gde je svako polje numerisano rednim brojem obilaska (od 1 do n×n).

Primer:

Ulaz:
5

Izlaz (primer jednog obilaska):
 1  6 15 10 21
14  9 20  5 16
19  2  7 22 11
 8 13 24 17  4
25 18  3 12 23
  

Uputstvo i ideja rešenja

Knight's Tour je jedan od najpoznatijih primera bektreking algoritma. Ideja je sledeća:

  • Krećemo od početnog polja i zapisujemo broj poteza (1, 2, 3, …).
  • Konj ima maksimalno 8 mogućih skokova – proveravamo ih redom.
  • Ako je sledeće polje slobodno i unutar table, prelazimo na njega.
  • Ako više nema mogućih skokova → vraćamo se unazad (backtracking).
  • Kada smo popunili n×n polja, dobili smo validan obilazak.

Zbog složenosti problema, traženje obilaska se oslanja na pretragu po dubini i pametno odbacivanje pozicija koje vode u ćorsokak.

Rešenje u C++ jeziku


#include <iostream>
#include <vector>
using namespace std;

int n;
vector<vector<int>> tabla;

// Svi mogući skokovi konja
int dx[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int dy[8] = { 1, 2,  2,  1, -1, -2, -2, -1 };

// Proverava da li je potez validan
bool validno(int x, int y) {
    return (x >= 0 && x < n && y >= 0 && y < n && tabla[x][y] == 0);
}

// Rekurzivna funkcija za obilazak konja
bool obilazak(int x, int y, int korak) {
    if (korak == n * n)
        return true; // Svi potezi uspešno napravljeni

    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        if (validno(nx, ny)) {
            tabla[nx][ny] = korak + 1;

            if (obilazak(nx, ny, korak + 1))
                return true;

            tabla[nx][ny] = 0; // Backtracking
        }
    }
    return false;
}

int main() {
    cout << "Unesite dimenziju table n (5 <= n <= 10): ";
    cin >> n;

    if (n < 5 || n > 10) {
        cout << "Dozvoljene vrednosti su od 5 do 10." << endl;
        return 1;
    }

    tabla.assign(n, vector<int>(n, 0));

    // Početna pozicija konja (0, 0)
    tabla[0][0] = 1;

    if (obilazak(0, 0, 1)) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cout << tabla[i][j] << "\t";
            }
            cout << endl;
        }
    } else {
        cout << "Nema rešenja za zadatu tablu." << endl;
    }

    return 0;
}
  

Objašnjenje koda

Program koristi matricu tabla gde se čuva redni broj obilaska.

  • validno() proverava da li je potez dozvoljen: unutar table i neposećen.
  • obilazak() rekurzivno pokušava 8 poteza konja.
  • Ako se popuni n×n poteza, rešenje je pronađeno.
  • Ako se dođe u ćorsokak → vraćamo se (backtracking).

Komentar o efikasnosti i poboljšanjima

Osnovni backtracking za Knight's Tour ima veoma veliku složenost (eksponencijalnu). Za male table radi dobro, ali za veće postaje spor.

Moguća poboljšanja:

  • Warnsdorffovo pravilo – uvek birati potez sa najmanje nastavaka. Drastično ubrzava algoritam.
  • Korišćenje heuristika za redukovanje grananja.
  • Korišćenje bitmapi za optimizaciju provere zauzetosti.
  • Memorisanje problematičnih konfiguracija.

U praksi, Warnsdorffova heuristika može da pronađe rešenje na tabli 8×8 za nekoliko milisekundi.

Varijanta 1 — Detaljno komentarisano C++ rešenje (gruba sila + backtracking)

U ovoj sekciji nalazi se u potpunosti komentarisana verzija osnovnog backtracking algoritma za problem obilaska konja. Cilj je da se korisniku jasno prikaže šta se dešava u svakom koraku algoritma.

Ovo je odličan dodatni materijal za učenike koji žele da razumeju:

  • šta znači “proveriti validan potez”,
  • kako funkcioniše rekurzija u backtracking algoritmu,
  • na koji način se vrši “vraćanje unazad” (undo poteza),
  • kako izgleda standardna struktura jednog rekurzivnog pretraživača.

Potpuno komentarisani C++ kod (Varijanta 1)


// -----------------------------------------------------------
//   OBILAZAK KONJA – Varijanta 1 (gruba sila + backtracking)
//   Kompletno objašnjena verzija koda, sa komentarima reda-po-red.
// -----------------------------------------------------------

#include <iostream>
#include <vector>
using namespace std;

// Sva 8 moguća pomeranja konja
int dx[8] = { 2, 1, -1, -2, -2, -1,  1, 2 };
int dy[8] = { 1, 2,  2,  1, -1, -2, -2, -1 };

// Proveravamo da li je moguće preći na polje (x, y)
bool valid(int x, int y, int n, vector>& board) {
    // Mora biti unutar table
    if (x < 0 || x >= n) return false;
    if (y < 0 || y >= n) return false;

    // Polje mora biti neuslovljeno (0 znači neposećeno)
    if (board[x][y] != 0) return false;

    return true;
}

// Glavna rekurzivna funkcija
bool tour(int x, int y, int step, int n, vector>& board) {
    // Ako smo popunili sva n*n polja → kraj!
    if (step == n*n)  
        return true;

    // Prolazimo kroz svih 8 mogućih poteza konja
    for (int i = 0; i < 8; i++) {

        // Računamo novo polje
        int nx = x + dx[i];
        int ny = y + dy[i];

        // Provera da li je potez dozvoljen
        if (valid(nx, ny, n, board)) {

            // -------------------------------
            // 1) Postavljamo konja na novo polje
            // -------------------------------
            board[nx][ny] = step + 1;

            // -------------------------------
            // 2) Rekurzivno nastavljamo obilazak
            // -------------------------------
            if (tour(nx, ny, step + 1, n, board))
                return true; // Ako uspe → gotovo

            // -------------------------------
            // 3) BACKTRACKING (vraćamo se unazad)
            //    Ako rekurzija NIJE našla rešenje,
            //    poništavamo potez i pokušavamo sledeći.
            // -------------------------------
            board[nx][ny] = 0;
        }
    }

    // Ako nijedan potez iz ove pozicije ne vodi do rešenja
    return false;
}

int main() {
    int n;
    cin >> n;

    // Tabla inicijalno puna nula (neposećena polja)
    vector> board(n, vector(n, 0));

    // Startna pozicija: (0,0)
    board[0][0] = 1;

    // Pokrećemo backtracking algoritam
    if (tour(0, 0, 1, n, board)) {
        cout << "Pronadjeno resenje:\n";
        for (auto& row : board) {
            for (int cell : row)
                cout << cell << "\t";
            cout << "\n";
        }
    } else {
        cout << "Nema resenja.\n";
    }
}
  

Objašnjenje ključnih tačaka u kodu

  • valid() proverava da li je polje unutar table i da li još nije posećeno.
  • tour() je srce algoritma:
    • prima trenutnu poziciju (x, y), broj koraka i tablu,
    • u svakom koraku pokušava svih 8 poteza,
    • rekurzivno prati jednu granu dok god je validna,
    • ako zapne → vrati se unazad (backtracking),
    • kada ispuni n*n → uspeh.
  • Backtracking deo: Ako rekurzija ne uspe, potez se “poništava”:
    board[nx][ny] = 0;
    Ovo je ključni trenutak – algoritam se vraća jednu poziciju unazad i pokušava drugi put.
  • U main() samo postavljamo tablu, start i pozivamo funkciju.

Zašto je ova verzija važna?

Iako ova verzija nije najbrža, predstavlja najvažniji obrazovni primer. Korisnicima se jasno vidi šta je:

  • rekurzija,
  • grananje pretrage,
  • povratak unazad,
  • proceduralno građenje rešenja.

Ovako detaljno komentarisano rešenje je korak ka razumevanju složenijih heuristika (Varijanta 2, Varijanta 3).

Obilazak konja – Varijanta 2 (optimizovani backtracking pomoću Warnsdorffove heuristike)

Zadatak:
Napisati program koji pronalazi putanju konja na šahovskoj tabli dimenzije n × n tako da konj obiđe sva polja tačno jednom (Knight's Tour). U ovoj varijanti koristi se optimizovani pristup koji značajno ubrzava izvođenje algoritma.

Ulaz: Unosi se broj n (5 ≤ n ≤ 10).
Izlaz: Ispisati tablu sa rednim brojem poteza kojim je obiđeno svako polje.

Ideja rešenja – Warnsdorffova heuristika

Osnovni backtracking isprobava sve moguće skokove konja bez reda, što dovodi do ogromnog grananja i usporava algoritam za veće table. Warnsdorffova heuristika uvodi sledeće pravilo:

„U svakom koraku biraj onaj potez konja koji ima najmanji broj daljih mogućih poteza.“

Ovo pravilo čini algoritam znatno efikasnijim i omogućava pronalaženje rešenja za veće table mnogo brže nego čisti backtracking.

Koraci algoritma

  • Definisati svih 8 mogućih skokova konja.
  • U svakom koraku sakupiti sve validne skokove.
  • Za svaki skok izračunati njegov "stepen" – koliko ima nastavaka.
  • Sortirati poteze rastuće po stepenu.
  • Prvo pokušati one poteze koji ostavljaju najmanje mogućnosti.

Rešenje u C++ jeziku (Varijanta 2 – optimizovano)


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int n;
vector<vector<int>> tabla;

int dx[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int dy[8] = { 1, 2,  2,  1, -1, -2, -2, -1 };

// Proverava da li je polje validno za kretanje
bool validno(int x, int y) {
    return x >= 0 && x < n && y >= 0 && y < n && tabla[x][y] == 0;
}

// Izračunava "stepen" – koliko konj ima nastavaka iz ove pozicije
int stepen(int x, int y) {
    int count = 0;
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (validno(nx, ny)) count++;
    }
    return count;
}

// Optimizovani rekurzivni obilazak
bool obilazak(int x, int y, int korak) {
    if (korak == n * n) 
        return true;

    vector<pair<int, int>> potezi;

    // Skup svih mogućih poteza + njihov stepen
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        if (validno(nx, ny)) {
            int s = stepen(nx, ny);
            potezi.push_back({s, i});
        }
    }

    // Warnsdorff: sortiranje po rastućem stepenu
    sort(potezi.begin(), potezi.end());

    // Pokušaj po najboljem redosledu
    for (auto &p : potezi) {
        int i = p.second;
        int nx = x + dx[i], ny = y + dy[i];

        tabla[nx][ny] = korak + 1;

        if (obilazak(nx, ny, korak + 1))
            return true;

        tabla[nx][ny] = 0; // povratak (backtracking)
    }

    return false;
}

int main() {
    cout << "Unesite n (5 <= n <= 10): ";
    cin >> n;

    if (n < 5 || n > 10) {
        cout << "Dozvoljene vrednosti su od 5 do 10." << endl;
        return 1;
    }

    tabla.assign(n, vector<int>(n, 0));

    // Konj kreće iz gornjeg levog ugla
    tabla[0][0] = 1;

    if (obilazak(0, 0, 1)) {
        for (auto &red : tabla) {
            for (int polje : red)
                cout << polje << "\t";
            cout << endl;
        }
    } else {
        cout << "Nema rešenja!" << endl;
    }

    return 0;
}
  

Objašnjenje ključnih delova

  • stepen(x, y) – računa koliko nastavaka dat potez ima.
  • potezi – lista validnih poteza zajedno sa brojem budućih opcija.
  • sort(potezi.begin(), potezi.end()) – prvo pokušava najteža polja.
  • Na taj način algoritam drastično smanjuje broj provera.

Zašto je varijanta 2 mnogo brža?

Umesto da algoritam lutajući ispituje preko 100–1000 puta više grana, Warnsdorffov pristup vodi konja „najkritičnijim putem“ i čini verovatnijim da obilazak uspe bez povratka.

Rezultati u praksi

  • Za n = 5 → rešenje se dobija gotovo instant.
  • Za n = 8 (klasična tabla) → rešenje se dobija u milisekundama.
  • Čisti backtracking bi za n = 8 trajao predugo bez optimizacija.

Zaključak

Ovo rešenje predstavlja značajno unapređenje osnovnog backtracking pristupa. Warnsdorffova heuristika je jednostavna za implementaciju, a pruža ogromno ubrzanje.

Ova varijanta može služiti kao uvod u još naprednije tehnike poput iterativnog poboljšanja (local search) i heuristike zasnovane na zaključivanju.

Obilazak konja – Varijanta 2 (Warnsdorffova heuristika) — dodatne implementacije

U nastavku su dve dodatne implementacije Varijante 2: Python i C#. Oba rešenja koriste Warnsdorffovo pravilo za izbor narednog poteza.

Rešenje u Pythonu (Varijanta 2)


#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10000)

dx = [2, 1, -1, -2, -2, -1, 1, 2]
dy = [1, 2, 2, 1, -1, -2, -2, -1]

def valid(x, y, n, board):
    return 0 <= x < n and 0 <= y < n and board[x][y] == 0

def degree(x, y, n, board):
    cnt = 0
    for i in range(8):
        nx, ny = x + dx[i], y + dy[i]
        if valid(nx, ny, n, board):
            cnt += 1
    return cnt

def tour(x, y, step, n, board):
    if step == n * n:
        return True

    moves = []
    for i in range(8):
        nx, ny = x + dx[i], y + dy[i]
        if valid(nx, ny, n, board):
            moves.append((degree(nx, ny, n, board), nx, ny))

    # sortiraj po rastućem stepenu (Warnsdorff)
    moves.sort(key=lambda t: t[0])

    for _, nx, ny in moves:
        board[nx][ny] = step + 1
        if tour(nx, ny, step + 1, n, board):
            return True
        board[nx][ny] = 0  # backtrack

    return False

def main():
    try:
        n = int(input("Unesite n (5 <= n <= 10): ").strip())
    except:
        print("Nevažeći unos.")
        return

    if n < 5 or n > 10:
        print("Dozvoljene vrednosti su od 5 do 10.")
        return

    board = [[0] * n for _ in range(n)]
    board[0][0] = 1

    if tour(0, 0, 1, n, board):
        for row in board:
            print("\t".join(str(x) for x in row))
    else:
        print("Nema rešenja.")

if __name__ == "__main__":
    main()
  

Objašnjenje (Python)

  • degree računa koliko validnih poteza ima dato polje — to je kriterijum za Warnsdorff.
  • U tour funkciji skupljamo sve validne poteze, sortiramo ih po stepenu i pokušavamo ih u tom redu.
  • Rezultat se ispisuje kao matrica rednih brojeva obilaska.

Rešenje u C# (Varijanta 2)


using System;
using System.Collections.Generic;

class Program {
    static int n;
    static int[,] board;
    static int[] dx = { 2, 1, -1, -2, -2, -1, 1, 2 };
    static int[] dy = { 1, 2, 2, 1, -1, -2, -2, -1 };

    static bool Valid(int x, int y) {
        return x >= 0 && x < n && y >= 0 && y < n && board[x, y] == 0;
    }

    static int Degree(int x, int y) {
        int cnt = 0;
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (Valid(nx, ny)) cnt++;
        }
        return cnt;
    }

    static bool Tour(int x, int y, int step) {
        if (step == n * n) return true;

        var moves = new List>(); // (degree, nx, ny)
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (Valid(nx, ny)) {
                moves.Add(Tuple.Create(Degree(nx, ny), nx, ny));
            }
        }

        // sortiramo po stepenu (rastuce)
        moves.Sort((a,b) => a.Item1.CompareTo(b.Item1));

        foreach (var m in moves) {
            int nx = m.Item2, ny = m.Item3;
            board[nx, ny] = step + 1;
            if (Tour(nx, ny, step + 1)) return true;
            board[nx, ny] = 0; // backtrack
        }

        return false;
    }

    static void Main() {
        Console.Write("Unesite n (5 <= n <= 10): ");
        if (!int.TryParse(Console.ReadLine(), out n)) return;
        if (n < 5 || n > 10) {
            Console.WriteLine("Dozvoljene vrednosti su od 5 do 10.");
            return;
        }

        board = new int[n, n];
        board[0, 0] = 1;

        if (Tour(0, 0, 1)) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    Console.Write(board[i, j] + "\t");
                }
                Console.WriteLine();
            }
        } else {
            Console.WriteLine("Nema rešenja.");
        }
    }
}
  

Objašnjenje (C#)

  • Ista logika kao u C++ i Python verzijama: Degree i sortiranje poteza po stepenu.
  • Korišćena je lista tuple-ova za sortiranje poteza; zatim se pokušava svaki potez u redu.

Predlozi za integraciju na stranicu

  • Dodaj ova dva koda ispod C++ dela kao „Dodatne implementacije”.
  • Možeš dodati <details> HTML blokove oko dugih kodova da strani bude preglednija.
  • Za bolju interakciju — razmisli o dodavanju dugmeta za preuzimanje koda (plain .py i .cs fajlovi).

Obilazak konja – Varijanta 3 (čisto heurističko rešenje, bez backtrackinga)

Za razliku od Varijante 1 (gruba sila) i Varijante 2 (backtracking + Warnsdorff), ova varijanta uopšte ne koristi povratak unazad (backtracking).

Algoritam koristi isključivo Warnsdorffovo pravilo: u svakom koraku bira se potez koji vodi do polja sa najmanjim brojem daljih validnih poteza.

Ovaj čist heuristički pristup je veoma brz (linearna složenost O(n²)) i u praksi daje rešenje za sve table dimenzija n ≥ 5.

C++ implementacija (Varijanta 3)


#include <bits/stdc++.h>
using namespace std;

int dx[8] = {2,1,-1,-2,-2,-1,1,2};
int dy[8] = {1,2,2,1,-1,-2,-2,-1};

bool valid(int x, int y, int n, vector>& board) {
    return x >= 0 && x < n && y >= 0 && y < n && board[x][y] == 0;
}

int degree(int x, int y, int n, vector>& board) {
    int cnt = 0;
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (valid(nx, ny, n, board)) cnt++;
    }
    return cnt;
}

bool warnsdorff(int n, vector>& board, int sx = 0, int sy = 0) {
    int x = sx, y = sy;
    board[x][y] = 1;

    for (int step = 2; step <= n*n; step++) {
        int bestDeg = 9, bestX = -1, bestY = -1;

        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (valid(nx, ny, n, board)) {
                int d = degree(nx, ny, n, board);
                if (d < bestDeg) {
                    bestDeg = d;
                    bestX = nx;
                    bestY = ny;
                }
            }
        }

        if (bestX == -1) return false; // heuristika propala

        x = bestX;
        y = bestY;
        board[x][y] = step;
    }

    return true; // uspešno
}

int main() {
    int n;
    cin >> n;

    vector> board(n, vector(n, 0));

    if (warnsdorff(n, board)) {
        for (auto& r : board) {
            for (int x : r) cout << x << "\t";
            cout << "\n";
        }
    } else {
        cout << "Nema rešenja.\n";
    }
}
  

Python implementacija (Varijanta 3)


dx = [2,1,-1,-2,-2,-1,1,2]
dy = [1,2,2,1,-1,-2,-2,-1]

def valid(x, y, n, board):
    return 0 <= x < n and 0 <= y < n and board[x][y] == 0

def degree(x, y, n, board):
    cnt = 0
    for i in range(8):
        nx, ny = x + dx[i], y + dy[i]
        if valid(nx, ny, n, board):
            cnt += 1
    return cnt

def warnsdorff(n, board, sx=0, sy=0):
    x, y = sx, sy
    board[x][y] = 1

    for step in range(2, n*n + 1):
        bestDeg = 9
        best = None

        for i in range(8):
            nx, ny = x + dx[i], y + dy[i]
            if valid(nx, ny, n, board):
                d = degree(nx, ny, n, board)
                if d < bestDeg:
                    bestDeg = d
                    best = (nx, ny)

        if best is None:
            return False

        x, y = best
        board[x][y] = step

    return True

def main():
    n = int(input("Unesite n (>= 5): "))
    board = [[0]*n for _ in range(n)]

    if warnsdorff(n, board):
        for row in board:
            print("\t".join(str(x) for x in row))
    else:
        print("Nema rešenja.")

if __name__ == "__main__":
    main()
  

C# implementacija (Varijanta 3)


using System;

class Program {
    static int[] dx = { 2, 1, -1, -2, -2, -1, 1, 2 };
    static int[] dy = { 1, 2, 2, 1, -1, -2, -2, -1 };

    static bool Valid(int x, int y, int n, int[,] board) {
        return x >= 0 && x < n && y >= 0 && y < n && board[x, y] == 0;
    }

    static int Degree(int x, int y, int n, int[,] board) {
        int cnt = 0;
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (Valid(nx, ny, n, board)) cnt++;
        }
        return cnt;
    }

    static bool Warnsdorff(int n, int[,] board, int sx = 0, int sy = 0) {
        int x = sx, y = sy;
        board[x, y] = 1;

        for (int step = 2; step <= n * n; step++) {
            int bestDeg = 9;
            int bestX = -1, bestY = -1;

            for (int i = 0; i < 8; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if (Valid(nx, ny, n, board)) {
                    int d = Degree(nx, ny, n, board);
                    if (d < bestDeg) {
                        bestDeg = d;
                        bestX = nx;
                        bestY = ny;
                    }
                }
            }

            if (bestX == -1)
                return false;

            x = bestX;
            y = bestY;
            board[x, y] = step;
        }

        return true;
    }

    static void Main() {
        int n = int.Parse(Console.ReadLine());
        int[,] board = new int[n, n];

        if (Warnsdorff(n, board)) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    Console.Write(board[i, j] + "\t");
                }
                Console.WriteLine();
            }
        } else {
            Console.WriteLine("Nema rešenja.");
        }
    }
}
  

Karakteristike Varijante 3

  • Izuzetno brzo rešenje — praktično O(n²).
  • Nema povratka unazad: svaki potez je konačan.
  • Uvek daje rešenje za n ≥ 5 (osim retkih patoloških kombinacija startne pozicije, koje se mogu izbeći rotacijom/simetrijom).
  • Minimalan kod i izuzetno elegantna heuristika.

Napomena i dodatni resurs

Ako te zanima naprednija primena konja na šahovskoj tabli, pogledaj i stranicu Skakač napada – analiza i rešenja .

Članak objašnjava kako koristiti konja za napad na tabli, prikazuje različite algoritamske pristupe i optimizacije, uključujući upotrebu unija u C++ za efikasnije praćenje pozicija. Čitanjem ovog članka možeš steći bolji uvid u strategije kretanja konja i unaprediti razumevanje backtracking-a u kontekstu šaha.

Ukratko, dok je Knight's Tour zadatak fokusiran na obilazak svih polja, članak Skakač napada pokazuje kako se konj može koristiti u napadačkim situacijama i kako algoritamski pristupi mogu biti optimizovani za praktične primene.

Izvori i reference

Neki zadaci i ideje algoritama inspirisani su sledećim izvorima, ali svi kodovi i objašnjenja su originalni i prilagođeni za SvetProgramiranja:

Napomena: svi kodovi su kreirani posebno za SvetProgramiranja i prilagođeni za edukativnu upotrebu.


Prethodno
​|<Priprema za drzavno takmičenje i SIO