#include #include #include #define KNIGHTS 5 // numbers of knights #define UNKNOWN -1 typedef struct pos { int x; int y; } pos; int N; int **checkboard; pos knight[KNIGHTS]; pos target[KNIGHTS]; // Počet skoků pro každého koně do každého cíle int distance[KNIGHTS][KNIGHTS]; // Datová struktura FRONTA typedef struct fifo { pos position; int distance; struct fifo* next; } fifo; fifo* first; fifo* last; void fifo_init() { first = NULL; } fifo* fifo_pop() { fifo* current = first; if (first != NULL) first = first->next; return current; } void fifo_push(int x, int y, int distance) { fifo* current = malloc(sizeof(fifo)); current->position.x = x; current->position.y = y; current->distance = distance; current->next = NULL; if (first == NULL) first = last = current; else { last->next = current; last = current; } } // Datová struktura FRONTA - konec // Připraví šachovnici (vyplní všude UNKNOWN) void init_checkboard() { for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) checkboard[x][y] = UNKNOWN; } // Přidá políčko do fronty, pokud je validní void add_place(int x, int y, int distance) { // Pokud je pozice mimo -> nic nedělej if (x < 0 || x >= N || y < 0 || y >= N) return; // Pokud je pozice již navštívená -> nic nedělej if (checkboard[x][y] != UNKNOWN) return; // Jinak přidej pozici do fronty fifo_push(x, y, distance); } // Prohledá šachovnici pro daného koně a vyplní nalezené vzdálenosti do tabulky void search_checkboard(int knight_index) { // Kolik cílů jsme již našli, pro zastavení prohledávání celé šachovnice int found = 0; for (int i = 0; i < KNIGHTS; i++) distance[knight_index][i] = UNKNOWN; init_checkboard(); fifo_init(); fifo_push(knight[knight_index].x, knight[knight_index].y, 0); // Do fronty jsme vložili výchozí pozici koně. Teď, dokud ve frontě bude // něco zbývat, prohledáme do šířky šachovnici (na každé pozici přidáme // do fronty zatím nenavštívené "sousedy") a přitom si zapisujeme, jak // dlouho nám to kam trvá. fifo* current = fifo_pop(); while (current != NULL) { int x = current->position.x; int y = current->position.y; int d = current->distance; // 1. Pokud je pozice ještě nenavštívená, zpracujeme ji if (checkboard[x][y] == UNKNOWN) { checkboard[x][y] = d; // 2. Zkontrolujeme dosažení cíĺů for (int i = 0; i < KNIGHTS; i++) { if (target[i].x == x && target[i].y == y) { distance[knight_index][i] = d; found++; } } // 3. Přidáme všechna okolní políčka (8 možných skoků) // -> funkci můžeme předat i neplatné pozice, ona dál // propustí jen ty validní add_place(x-1, y-2, d+1); add_place(x+1, y-2, d+1); add_place(x-2, y-1, d+1); add_place(x+2, y-1, d+1); add_place(x-2, y+1, d+1); add_place(x+2, y+1, d+1); add_place(x-1, y+2, d+1); add_place(x+1, y+2, d+1); } // 4. Posuneme se na další prvek free(current); current = fifo_pop(); // 5. Pokud už jsme našli všechny cíle, ukončíme if (found == KNIGHTS) break; } // Vyprázdníme frontu, pokud v ní něco zbylo while (current != NULL) { free(current); current = fifo_pop(); } } bool target_used[KNIGHTS]; int find_best(int knight_index) { int minimum = N*N; for (int i = 0; i < KNIGHTS; i++) { if (target_used[i]) continue; if (knight_index == KNIGHTS - 1) minimum = distance[knight_index][i]; else { // Zkusíme použít tento cíl pro tohoto koně a zavoláme se na zbytek volných cílů target_used[i] = true; int x = find_best(knight_index + 1); // Průběžně si počítáme dosažené minimum if (x + distance[knight_index][i] < minimum) minimum = x + distance[knight_index][i]; // Vrátíme cíl zpět mezi nepoužité (a zkusíme třeba jiný) target_used[i] = false; } } return minimum; } int main() { // 1. Načteme velikost a vyrobíme si šachovnici scanf("%d", &N); checkboard = malloc(sizeof(int*) * N); for (int i = 0; i < N; i++) checkboard[i] = malloc(sizeof(int) * N); // 2. Načteme pozice koní a cílů a spustíme 5 prohledání for (int i = 0; i < KNIGHTS; i++) scanf("%d %d", &knight[i].x, &knight[i].y); for (int i = 0; i < KNIGHTS; i++) scanf("%d %d", &target[i].x, &target[i].y); for (int i = 0; i < KNIGHTS; i++) search_checkboard(i); // 3. Máme vzdálenosti každý kůň <-> každý cíl, najdeme tu nejlepší kombinaci for (int i = 0; i < KNIGHTS; i++) target_used[i] = false; printf("%d\n",find_best(0)); // 4. Pokud by nás zajímaly i jednotlivé vzdálenosti /*for (int i = 0; i < KNIGHTS; i++) { printf("Kun %d:\t", i); for (int j = 0; j < KNIGHTS; j++) printf(" %d", distance[i][j]); printf("\n"); }*/ return 0; }