#include <bits/stdc++.h> using namespace std; int n, L; vector<string> duties; // Funkcja obliczająca NWD int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } // Sprawdzanie, czy dane T jest możliwe bool check(double T) { vector<pair<double, double>> sleep(n); // przedziały snu // Przydzielamy sen dla każdej osoby for (int i = 0; i < n; i++) { double longest_free = 0; double current_free = 0; double best_start = 0; double current_start = 0; for (int j = 0; j <= L; j++) { if (j == L || duties[i][j] == 'X') { if (current_free > longest_free) { longest_free = current_free; best_start = current_start; } current_free = 0; current_start = j + 1; } else { current_free += 1.0; } } if (longest_free < T) return false; sleep[i] = {best_start, best_start + T}; } // Sprawdzamy ciągłe pokrycie for (double t = 0; t < L; t += 0.001) { bool covered = false; for (int i = 0; i < n; i++) { if (t < sleep[i].first || t >= sleep[i].second) { // nie śpi int segment = floor(t); if (duties[i][segment] == '.') { // nie ma obowiązków covered = true; break; } } } if (!covered) return false; } return true; } int main() { cin >> n >> L; duties.resize(n); for (int i = 0; i < n; i++) { cin >> duties[i]; } // Binary search na T double left = 0; double right = L; double eps = 1e-6; for (int iter = 0; iter < 100; iter++) { double mid = (left + right) / 2; if (check(mid)) { left = mid; } else { right = mid; } } double T = left; // Sprawdzamy, czy T jest możliwe (zamiast T - eps, co było zbyt restrykcyjne) if (!check(T)) { cout << "-1\n"; return 0; } if (T < eps) { cout << "0/1\n"; return 0; } // Konwersja na ułamek nieskracalny int best_num = 0, best_den = 1; double min_error = 1e9; for (int den = 1; den <= L; den++) { int num = round(T * den); double error = abs(T - (double)num / den); if (error < min_error) { min_error = error; int g = gcd(abs(num), den); best_num = num / g; best_den = den / g; } } if (min_error < eps) { cout << best_num << "/" << best_den << "\n"; } else { cout << "-1\n"; } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | #include <bits/stdc++.h> using namespace std; int n, L; vector<string> duties; // Funkcja obliczająca NWD int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } // Sprawdzanie, czy dane T jest możliwe bool check(double T) { vector<pair<double, double>> sleep(n); // przedziały snu // Przydzielamy sen dla każdej osoby for (int i = 0; i < n; i++) { double longest_free = 0; double current_free = 0; double best_start = 0; double current_start = 0; for (int j = 0; j <= L; j++) { if (j == L || duties[i][j] == 'X') { if (current_free > longest_free) { longest_free = current_free; best_start = current_start; } current_free = 0; current_start = j + 1; } else { current_free += 1.0; } } if (longest_free < T) return false; sleep[i] = {best_start, best_start + T}; } // Sprawdzamy ciągłe pokrycie for (double t = 0; t < L; t += 0.001) { bool covered = false; for (int i = 0; i < n; i++) { if (t < sleep[i].first || t >= sleep[i].second) { // nie śpi int segment = floor(t); if (duties[i][segment] == '.') { // nie ma obowiązków covered = true; break; } } } if (!covered) return false; } return true; } int main() { cin >> n >> L; duties.resize(n); for (int i = 0; i < n; i++) { cin >> duties[i]; } // Binary search na T double left = 0; double right = L; double eps = 1e-6; for (int iter = 0; iter < 100; iter++) { double mid = (left + right) / 2; if (check(mid)) { left = mid; } else { right = mid; } } double T = left; // Sprawdzamy, czy T jest możliwe (zamiast T - eps, co było zbyt restrykcyjne) if (!check(T)) { cout << "-1\n"; return 0; } if (T < eps) { cout << "0/1\n"; return 0; } // Konwersja na ułamek nieskracalny int best_num = 0, best_den = 1; double min_error = 1e9; for (int den = 1; den <= L; den++) { int num = round(T * den); double error = abs(T - (double)num / den); if (error < min_error) { min_error = error; int g = gcd(abs(num), den); best_num = num / g; best_den = den / g; } } if (min_error < eps) { cout << best_num << "/" << best_den << "\n"; } else { cout << "-1\n"; } return 0; } |