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";

Podobne dokumenty