// Úloha: 28-5-6 Sloty na Iridium // Autor programu: Jirka Setnička #include #include #include #define MIN(a,b) (((a)<(b))?(a):(b)) int O, S, K; int *sloty; // Vrátí kratší ze vzdáleností mezi dvěma sloty (zadanými indexy) int d(int a, int b) { // Vzdálenost bez přechodu 0 a vzdálenost přes 0 if (sloty[a] > sloty[b]) return MIN(sloty[a] - sloty[b], O - sloty[a] + sloty[b]); else return MIN(sloty[b] - sloty[a], O - sloty[b] + sloty[a]); } // Funkce testující, jestli rozmístění iridia po zadaných vzdálenostech funguje bool rozmisti(int D, bool vypsat) { int iridium[K]; // 1. Prvotní rozmístění iridium[0] = 0; // Umístíme do prvního slotu int slot = 0; for (int i = 1; i < K; i++) { while (d(iridium[i - 1], slot) < D) { slot++; if (slot == S) return false; // Nepovedlo se rozmístit } iridium[i] = slot; } // 2. Zkontrolujeme vzdálenost mezi prvním a posledním (a případně začneme posouvat) int posledni_posunute = K - 1; // index naposledy posouvaného iridia int dalsi = 0; while (d(iridium[posledni_posunute], iridium[dalsi]) < D) { iridium[dalsi]++; // Posuneme o jeden slot dal // Posunuli jsme až na pozici, kde už jednou bylo první iridium, // takže tudy cesta nevede a s touto minimální vzdáleností to nepůjde if (iridium[dalsi] == S) return false; // Pokud uz jsme dost daleko od predchoziho... if (d(iridium[posledni_posunute], iridium[dalsi]) >= D) { posledni_posunute = dalsi; dalsi = (dalsi + 1) % K; } } // 3. Vše vyšlo, pokud máme vypsat pozice, tak je vypíšeme if (vypsat) { for (int i = 0; i < K - 1; i++) printf("%d ", iridium[i]); printf("%d\n", iridium[K - 1]); } return true; } int main(void) { // 1. Načtení vstupu scanf("%d %d %d", &O, &S, &K); sloty = malloc(sizeof(int) * S); for (int i = 0; i < S; i++) scanf("%d", &sloty[i]); // 2. Binárně vyhledáváme optimální vzdálenost mezi 1 a O/K (včetně) // (nejmenší vzdálenost dvou kousků iridia je 1, nejdále od sebe budou // při rovnoměrném rozmístění) int min = 1; int max = O/K; while (max != min) { // Najdeme si polovinu (když se trefíme mezi, vezmeme větší // z čísel, proto ta + 1 kvůli zaokrouhlování nahoru) int polovina = (min + max + 1) / 2; // Vejdou se, zkusíme vyhledávat větší if (rozmisti(polovina, false)) min = polovina; // Tahle vzdálenost už nefunguje, musí být menší else max = polovina - 1; } // 3. Zavoláme funkci rozmisti() znova na správnou vzdálenost a necháme // ji i vypsat výsledné indexy rozmisti(min, true); free(sloty); return 0; }