#include #include int N = 0; // Počet kotlů. int *data; // Údaje o přesunech (pozn: pole má o jeden prvek víc a indexujeme jej od 1). int free_place = 0; // Index posledního nalezeného volného kotle (pro dočasné odkládání hříšníků). // Načte data ze vstupního souboru do pole "data". void load_data() { FILE *fp = fopen("kotle.in", "r"); fscanf(fp, "%d\n", &N); data = (int*)malloc(sizeof(int) * (N+1)); for(int i = 1; i <= N; i++) fscanf(fp, "%d", data + i); fclose(fp); } // Nalezne nejbližší volný kotel, který lze použít jako dočasné odkladiště při rozbíjení cyklů. inline int get_free_place() { if ((free_place == 0) || (data[free_place] != 0)) { free_place = 1; while((free_place <= N) && (data[free_place] != 0)) free_place++; if (free_place > N) exit(1); // Tohle se nesmí podle zadání stát. } return free_place; } // Nalezne cestu nebo cyklus v přesunech počínaje kotlem "from" a zároveň v poli data obrátí ukazatele // přesunu (tj. místo toho, kam se má hříšník přesunout z daného kotle, bude u kotle uloženo, ze kterého kotle se má // hříšník přesunout do něj). // Funkce vrací index posledního prvku cesty (pokud je stejný, jako "from", pak je to cyklus). int find_path(int from) { if ((data[from] == from) || (data[from] == 0)) return 0; int next = data[from]; data[from] = 0; while(data[next] != 0) { int tmp = data[next]; data[next] = from; from = next; next = tmp; } data[next] = from; return next; } // Zpracuje cestu, která byla nalezena pomocí find_path a vypíše výsledky o přesunech do souboru fp. void process_path(int from, FILE *fp) { while(data[from] != 0) { fprintf(fp, "%d %d\n", data[from], from); int tmp = data[from]; data[from] = from; from = tmp; } } int main(int argc, char **argv) { load_data(); FILE *fp = fopen("kotle.out", "w"); for(int i = 1; i <= N; i++) { // Když narazíme na volné pole, zapamatujeme si jej, abychom učetřili práci funkci get_free_place(). if (data[i] == 0) free_place = i; if ((data[i] == 0) || (data[i] == i)) continue; // Nalezneme poslední prvek cesty/cyklu a cestu si připravíme. int last = find_path(i); int tmpPlace = 0; if (last == i) { // Pokud je to cyklus, musíme ho nejdřív rozbít (odložit si jednoho hříšníka dočasně stranou). tmpPlace = get_free_place(); fprintf(fp, "%d %d\n", data[i], tmpPlace); last = data[i]; data[i] = 0; } else free_place = i; // Zpracujeme cestu a vypíšeme přesuny. process_path(last, fp); if (tmpPlace) { // Pokud máme hříšníka uloženého stranou, tak si ho přesuneme na správné místo. fprintf(fp, "%d %d\n", tmpPlace, i); data[i] = i; } } fclose(fp); return 0; }