Organizujesz spływ kajakowy. Dana jest dopuszczalna ładowność
Transkrypt
Organizujesz spływ kajakowy. Dana jest dopuszczalna ładowność
Organizujesz spływ kajakowy. Dana jest dopuszczalna ładowność kajaka d, liczba osób n, oraz wagi wszystkich osób. Wyznacz minimalna liczbę potrzebnych kajaków (zadanie z 4 OI – 1997rok). Przykładowe dane i odpowiedzi: kaj0.in kaj3.in d=100, n=9 d=200, n=7 odp: 6 odp: 4 kaj5.in d=200, n=30000 odp: 15295 kaj8.in d=200, n=30000 odp: 15361 Rozwiązanie najprostsze Przydziel do kolejnych kajaków osób pojedynczo: od osoby najcięższej, ewentualnie dodaj jej drugą osobę do kajaka, aktualnie najlżejszą, jeśli się zmieści: 1. 2. 3. 4. 5. 6. Pobierz z pliku dane: dopuszczalną wagę kajaka i liczbę osób Pobierz z pliku do tablicy/wektora wagi kolejnych osób Posortuj osoby według wagi niemalejąco Licznik kajaków ustaw na 0 Indeks osoby najcięższej i ustaw na n-1, najlżejszej j na 0 Dopóki i>=j powtarzaj: 1. zwiększ licznik kajaków o 1 2. jeśli suma wag osoby aktualnie najcięższej i aktualnie najlżejszej <= d to wsadź najlżejszą do kajaka, przesuwając indeks j na następną osobę, czyli zwiększ j o 1 3. wsadź najcięższą osobę do kajaka, tzn. przesuń indeks i na następną osobę (zmniejsz i o 1) 7. wyświetl licznik kajaków Rozwiązanie wzorcowe Grupowanie osób o jednakowych wagach i zapełnianie na raz wielu kajaków zestawem osób o tych samych wagach 1. 2. 3. 4. Pobierz z pliku dane: dopuszczalną wagę kajaka d i liczbę osób uczestniczących w spływie n Utwórz tablicę B[d+1] - licznik osób o wagach z zakresu od 0 do d Kolejno czytaj z pliku wagę w osoby i inkrementuj właściwy element tablicy B: B[w]++ Znajdź najmniejszą wagę uczestniczącą w spływie, tzn. najmniejszy indeks w, dla którego element tablicy B[w]>0 5. Dopóki waga w<=d powtarzaj: 1. jeżeli zmieści się jeszcze ktoś w kajaku (2*w<dopuszczalna waga) 1. oblicz zapas wagi tego kajaka: z = d-w 2. dopóki B[w]>0 i z>w powtarzaj 1. zobacz ile jest osób o wadze z: jeśli B[z]=0 to przejdź do najbliższej mniejszej wagi z, dla której B[z]>0 2. oblicz ile można wziąć par o wagach w i z, będzie to min(B[w],B[z]) 3. zwiększ licznik kajaków o liczbę tych par 4. odejmij przydzieloną liczbę par od stanu B[w] i B[z] 5. przejdź do najbliższej mniejszej wagi z, dla której B[z]>0, ogranicz z od dołu: z>5 3. jeśli zostały jeszcze osoby o wadze w, to znaczy: B[w]>0 1. połącz je w pary: B[w]/2 zaokrąglone w górę do liczby całkowitej 2. zwiększ licznik kajaków o liczbę par 3. wyzeruj licznik osób o wadze w: B[w]=0 2. w przeciwnym razie, gdy druga osoba nie zmieści się do kajaka dla wszystkich kolejnych wag aż do 200 jeśli B[w]>0 to licznik kajaków zwiększ o B[w] 3. w++ 6. wyświetl licznik kajaków ifstream we("kaj0.in"); ------ ROZWIĄZANIE NAJPROSTSZE -----int n; // liczba osob vector <int> W; // wagi osob int d; // dopuszczalna waga kajaka int k = 0; // liczba kajakow we >> d >> n; cout << n <<" osob, max waga kajaka = " << d << endl; W.resize(n); for (int i=0; i<n; i++) we>>W[i]; // wczytanie wag osób z pliku do tablicy sort(W.begin(),W.end()); // sortowanie tablicy wag int i=n-1; // indeks osoby aktualnie najcięższej int j=0; // indeks osoby aktualnie najlżejszej while (i>=j) { // dopóki są osoby oczekujące na kajak k++; // weź kolejny kajak if ( i!=j && W[i]+W[j]<=d) j++; // jeśli oprócz osoby i-tej zmieści się osoba j-ta, to ją zapakuj i--; // zapakuj osobę i-tą } cout << k << " kajakow\n"; ------------------------------------- ROZWIĄZANIE WZORCOWE -----------------ifstream we("kaj0.in"); int n; // liczba wszystkich osob vector <int> W; // W[i] = liczba osob o wadze i int d; // dopuszczalna waga kajaka int k = 0; // liczba kajakow int w; // waga biezacej osoby we >> d >> n; cout << n <<" osob, max waga kajaka = " << d << endl; W.resize(d,0); for (int i=0; i<n; i++) { we>>w; W[w]++; } w=0; while (W[w]==0) w++; // znajdz najmniejsza wage while (w<d) { int zapas = d-w; if (zapas>=w) { // jezeli ktos sie jeszcze zmiesci while (W[w]>0 && zapas>w) { // jeżeli sa osoby o takich wagach while (W[zapas]==0) zapas--; if (W[w]<W[zapas]) { // ile jest par o wagach (w,zapas) k+=W[w]; W[zapas]-=W[w]; W[w]=0; } else { k+=W[zapas]; W[w]-=W[zapas]; W[zapas]=0; } } if (W[w]>0) { // jeśli zostały osoby o wadze w, połącz je w pary k += ceil(W[w]/2.0); // zaokrąglając w gore W[w]=0; } } else k += W[w]; // teraz już kazda osoba o wadze w wymaga osobnego kajaka w++; } cout << k << " kajakow\n";