Niestety, nie byliśmy w stanie w pełni poprawnie wyświetlić tego pliku, ponieważ nie jest zakodowany w UTF-8.
Możesz pobrać ten plik i spróbować otworzyć go samodzielnie.
#include "message.h" #include "kanapka.h" #include <iostream> #include <algorithm> using namespace std; int main() { /* 1) Wyznaczany jest rozmiar fragmentu oraz liczba instancji, kt�re maj� bra� udzia� w obliczeniach tak aby ka�da przetwarza�a co najmniej 100k 2) Ka�da instancja wyznacza i czyta sw�j fragment danych i od razu wylicza max sumy narastaj�co od prawej i sum�. 3) Wszystkie instancje opr�cz 0 wysy�aj� do 0: sum�, max sumy narastaj�co od prawej 4) Instacja 0 wyznacza sumy narastaj�co (od obu stron) i max sumy narastaj�cej od prawej na granicach przedzia��w i rozsy�a do pozosta�ych ich warto�ci. 5) Instancje wyznaczaj� najlepsze wyniki w swoich przedzia�ach i wysy�aj� do 0. 6) Instancja 0 zbiera odpowiedzi i wypisuje max jako wynik. */ int node = MyNodeId(); int n = GetN(); int nn = min(NumberOfNodes(), 1 + n / 100000); // ograniczenie liczby instancji aby ka�da mia�a min. 50-100k (lub ca�o�� dla n < 100k) if (node >= nn) return 0; // niepotrzebna instancja int s = n / nn; // d�ugo�� jednej sekcji int i0 = node * s; // pozycja pocz�tkowa int i1 = (node == nn - 1 ? n - 1 : (node + 1) * s - 1); // pozycja ko�cowa int i; long long sum; // suma sekcji long long maxr; // max z sum narastaj�co od prawej dla ka�dej pozycji long long sum_pop; // suma poprzednich sekcji long long sum_nast; // suma nast�pnych sekcji long long maxr_nast; // maksymalna suma narastaj�co od prawej w nast�pnych sekcjach long long *sumr100 = new long long[(i1 - i0 + 1) / 100 + 2]; // sumr100[k] suma narastaj�co od prawej z zakresu (i0 + 100*k)..i1 long long *maxr100 = new long long[(i1 - i0 + 1) / 100 + 2]; // maxr100[k] maksymalna suma narastaj�ca z zakresu (i0 + 100*k)..i1 // obliczenie sumy sekcji i maksymalnej sumy narastaj�cej od prawej ---------------------------------------------------- sum = maxr = GetTaste(i1); for (i = i1 - 1; i >= i0; --i) { sum += GetTaste(i); if (sum > maxr) maxr = sum; if((i - i0) % 100 == 0) { int k = (i - i0) / 100; sumr100[k] = sum; maxr100[k] = maxr; } } // wys�anie sum do serwera i odebranie wynikowych sum --------------------------------------------------------------------- if (node > 0) { PutLL(0, sum); PutLL(0, maxr); Send(0); Receive(0); sum_pop = GetLL(0); sum_nast = GetLL(0); maxr_nast = GetLL(0); } else if (nn > 1) { // s� inne instancje ------------------------------------------------------------------------------------- // serwer odbiera sumy, wyznacza i rozsy�a faktyczne sumy narastaj�co na kra�cach oraz max z sumy od prawej na kra�cach long long *tsum = new long long[nn]; long long *tmaxr = new long long[nn]; tsum[0] = sum; tmaxr[0] = maxr; // w praktyce to niepotrzebne bo nie b�dzie odwo�ania for(int odp = 0; odp < nn - 1; ++odp) { // trzeba zebra� nn - 1 komunikat�w int nadawca = Receive(-1); tsum[nadawca] = GetLL(nadawca); tmaxr[nadawca] = GetLL(nadawca); } long long *tsum_pop = new long long[nn]; // sumy poprzednich sekcji long long *tsum_nast = new long long[nn]; // sumy nast�pnych sekcji long long *tmaxr_nast = new long long[nn]; // maksymalna suma narastaj�co od prawej dla kolejnych sekcji tsum_pop[0] = 0; for (i = 1; i < nn; ++i) { tsum_pop[i] = tsum_pop[i - 1] + tsum[i - 1]; } tsum_nast[nn - 1] = tmaxr_nast[nn - 1] = 0; for (i = nn - 2; i >= 0; --i) { tsum_nast[i] = tsum_nast[i + 1] + tsum[i + 1]; /* maksymalna suma narastaj�co od prawej (w ca�ej kanapce) dla kolejnych sekcji to maksimum z 1) maksymalnej sumy w sekcjach "zakolejnych" (czyli kolejnych dla nast�pnej) 2) sumy "zakolejnych" sekcji i maksymalnej sumy narastaj�cej od prawej wewn�trz nast�pnej sekcji */ tmaxr_nast[i] = max(tmaxr_nast[i + 1], tsum_nast[i + 1] + tmaxr[i + 1]); } // wys�a� dane do pozosta�ych instancji for (i = 1; i < nn; ++ i) { PutLL(i, tsum_pop[i]); PutLL(i, tsum_nast[i]); PutLL(i, tmaxr_nast[i]); Send(i); } // ustawi� warto�ci dla serwera sum_pop = 0; sum_nast = tsum_nast[0]; maxr_nast = tmaxr_nast[0]; } else { // serwer dzia�a sam -------------------------------------------------------------------------- sum_pop = sum_nast = maxr_nast = 0; } // obliczenie najlepszego wyniku w sekcji ------------------------------------------------------------- int imaxr0; // pocz�tkowa pozycja od kt�rej b�d� trzymane dane w maxri long long maxri[100 + 1]; // maxr_i[i] - maksymalna suma narastaj�co w sekcji od pozycji imaxr0 + i (+1 na stra�nika) long long wynik = 0; sum = 0; for (i = i0; i <= i1; ++i) { if ((i - i0) % 100 == 0) { // obliczenie maksymalnych sum narastaj�co w sekcji od prawej dla kolejnych 100 pozycji int k = (i - i0) / 100; imaxr0 = i; maxr = i + 100 > i1 ? 0 : maxr100[k + 1]; long long sumr = i + 100 > i1 ? 0 : sumr100[k + 1]; int j1 = min(i1, i + 100 - 1); //i + 99 lub ostatni element maxri[j1 + 1 - imaxr0] = 0; // stra�nik for (int j = j1; j >= imaxr0; --j) { sumr += GetTaste(j); if (sumr > maxr) maxr = sumr; maxri[j - imaxr0] = maxr; } } sum += GetTaste(i); /* wynik przy za�o�eniu, �e z przodu gryziemy 0..i jest r�wny: suma poprzednich sekcji (0..i0-1) PLUS suma narastaj�co z aktualnej sekcji (i0..i) PLUS maksimum z: 1) 0 - to jest przypadek, �e z prawej nic si� nie da ugry�� 2) sumy wszystkich kolejnych sekcji (i1+1..n-1) oraz maksymalnej sumy narastaj�co od prawej w bie��cej sekcji za pozycj� i (i+1..i1) - to jest przypadek gdzie od prawej ugryziemy do miejsca w bie��cej sekcji 3) maksymalnej sumy narastaj�co od prawej do uzyskania gdzie� w kolejnych sekcjach (maxr_nast) - to jest przypadek gdzie od prawej ugryziemy do miejsca, kt�re jest w kolejnych sekcjach */ long long w = sum_pop + sum + max(0LL, max(sum_nast + maxri[i + 1 - imaxr0], maxr_nast)); // dla i == min(i1, imaxr0 + 100) b�dzie odwo�anie do stra�nika w maxr if (w > wynik) wynik = w; } if (node > 0) { // wys�anie wyniku do serwera -------------------------------------------------------------- PutLL(0, wynik); Send(0); } else { // odebranie odpowiedzi, wyznaczenie i wypisanie najlepszego wyniku for(int odp = 0; odp < nn - 1; ++odp) { int nadawca = Receive(-1); long long w = GetLL(nadawca); if (w > wynik) wynik = w; } cout << wynik << endl; } 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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #include "message.h" #include "kanapka.h" #include <iostream> #include <algorithm> using namespace std; int main() { /* 1) Wyznaczany jest rozmiar fragmentu oraz liczba instancji, kt�re maj� bra� udzia� w obliczeniach tak aby ka�da przetwarza�a co najmniej 100k 2) Ka�da instancja wyznacza i czyta sw�j fragment danych i od razu wylicza max sumy narastaj�co od prawej i sum�. 3) Wszystkie instancje opr�cz 0 wysy�aj� do 0: sum�, max sumy narastaj�co od prawej 4) Instacja 0 wyznacza sumy narastaj�co (od obu stron) i max sumy narastaj�cej od prawej na granicach przedzia��w i rozsy�a do pozosta�ych ich warto�ci. 5) Instancje wyznaczaj� najlepsze wyniki w swoich przedzia�ach i wysy�aj� do 0. 6) Instancja 0 zbiera odpowiedzi i wypisuje max jako wynik. */ int node = MyNodeId(); int n = GetN(); int nn = min(NumberOfNodes(), 1 + n / 100000); // ograniczenie liczby instancji aby ka�da mia�a min. 50-100k (lub ca�o�� dla n < 100k) if (node >= nn) return 0; // niepotrzebna instancja int s = n / nn; // d�ugo�� jednej sekcji int i0 = node * s; // pozycja pocz�tkowa int i1 = (node == nn - 1 ? n - 1 : (node + 1) * s - 1); // pozycja ko�cowa int i; long long sum; // suma sekcji long long maxr; // max z sum narastaj�co od prawej dla ka�dej pozycji long long sum_pop; // suma poprzednich sekcji long long sum_nast; // suma nast�pnych sekcji long long maxr_nast; // maksymalna suma narastaj�co od prawej w nast�pnych sekcjach long long *sumr100 = new long long[(i1 - i0 + 1) / 100 + 2]; // sumr100[k] suma narastaj�co od prawej z zakresu (i0 + 100*k)..i1 long long *maxr100 = new long long[(i1 - i0 + 1) / 100 + 2]; // maxr100[k] maksymalna suma narastaj�ca z zakresu (i0 + 100*k)..i1 // obliczenie sumy sekcji i maksymalnej sumy narastaj�cej od prawej ---------------------------------------------------- sum = maxr = GetTaste(i1); for (i = i1 - 1; i >= i0; --i) { sum += GetTaste(i); if (sum > maxr) maxr = sum; if((i - i0) % 100 == 0) { int k = (i - i0) / 100; sumr100[k] = sum; maxr100[k] = maxr; } } // wys�anie sum do serwera i odebranie wynikowych sum --------------------------------------------------------------------- if (node > 0) { PutLL(0, sum); PutLL(0, maxr); Send(0); Receive(0); sum_pop = GetLL(0); sum_nast = GetLL(0); maxr_nast = GetLL(0); } else if (nn > 1) { // s� inne instancje ------------------------------------------------------------------------------------- // serwer odbiera sumy, wyznacza i rozsy�a faktyczne sumy narastaj�co na kra�cach oraz max z sumy od prawej na kra�cach long long *tsum = new long long[nn]; long long *tmaxr = new long long[nn]; tsum[0] = sum; tmaxr[0] = maxr; // w praktyce to niepotrzebne bo nie b�dzie odwo�ania for(int odp = 0; odp < nn - 1; ++odp) { // trzeba zebra� nn - 1 komunikat�w int nadawca = Receive(-1); tsum[nadawca] = GetLL(nadawca); tmaxr[nadawca] = GetLL(nadawca); } long long *tsum_pop = new long long[nn]; // sumy poprzednich sekcji long long *tsum_nast = new long long[nn]; // sumy nast�pnych sekcji long long *tmaxr_nast = new long long[nn]; // maksymalna suma narastaj�co od prawej dla kolejnych sekcji tsum_pop[0] = 0; for (i = 1; i < nn; ++i) { tsum_pop[i] = tsum_pop[i - 1] + tsum[i - 1]; } tsum_nast[nn - 1] = tmaxr_nast[nn - 1] = 0; for (i = nn - 2; i >= 0; --i) { tsum_nast[i] = tsum_nast[i + 1] + tsum[i + 1]; /* maksymalna suma narastaj�co od prawej (w ca�ej kanapce) dla kolejnych sekcji to maksimum z 1) maksymalnej sumy w sekcjach "zakolejnych" (czyli kolejnych dla nast�pnej) 2) sumy "zakolejnych" sekcji i maksymalnej sumy narastaj�cej od prawej wewn�trz nast�pnej sekcji */ tmaxr_nast[i] = max(tmaxr_nast[i + 1], tsum_nast[i + 1] + tmaxr[i + 1]); } // wys�a� dane do pozosta�ych instancji for (i = 1; i < nn; ++ i) { PutLL(i, tsum_pop[i]); PutLL(i, tsum_nast[i]); PutLL(i, tmaxr_nast[i]); Send(i); } // ustawi� warto�ci dla serwera sum_pop = 0; sum_nast = tsum_nast[0]; maxr_nast = tmaxr_nast[0]; } else { // serwer dzia�a sam -------------------------------------------------------------------------- sum_pop = sum_nast = maxr_nast = 0; } // obliczenie najlepszego wyniku w sekcji ------------------------------------------------------------- int imaxr0; // pocz�tkowa pozycja od kt�rej b�d� trzymane dane w maxri long long maxri[100 + 1]; // maxr_i[i] - maksymalna suma narastaj�co w sekcji od pozycji imaxr0 + i (+1 na stra�nika) long long wynik = 0; sum = 0; for (i = i0; i <= i1; ++i) { if ((i - i0) % 100 == 0) { // obliczenie maksymalnych sum narastaj�co w sekcji od prawej dla kolejnych 100 pozycji int k = (i - i0) / 100; imaxr0 = i; maxr = i + 100 > i1 ? 0 : maxr100[k + 1]; long long sumr = i + 100 > i1 ? 0 : sumr100[k + 1]; int j1 = min(i1, i + 100 - 1); //i + 99 lub ostatni element maxri[j1 + 1 - imaxr0] = 0; // stra�nik for (int j = j1; j >= imaxr0; --j) { sumr += GetTaste(j); if (sumr > maxr) maxr = sumr; maxri[j - imaxr0] = maxr; } } sum += GetTaste(i); /* wynik przy za�o�eniu, �e z przodu gryziemy 0..i jest r�wny: suma poprzednich sekcji (0..i0-1) PLUS suma narastaj�co z aktualnej sekcji (i0..i) PLUS maksimum z: 1) 0 - to jest przypadek, �e z prawej nic si� nie da ugry�� 2) sumy wszystkich kolejnych sekcji (i1+1..n-1) oraz maksymalnej sumy narastaj�co od prawej w bie��cej sekcji za pozycj� i (i+1..i1) - to jest przypadek gdzie od prawej ugryziemy do miejsca w bie��cej sekcji 3) maksymalnej sumy narastaj�co od prawej do uzyskania gdzie� w kolejnych sekcjach (maxr_nast) - to jest przypadek gdzie od prawej ugryziemy do miejsca, kt�re jest w kolejnych sekcjach */ long long w = sum_pop + sum + max(0LL, max(sum_nast + maxri[i + 1 - imaxr0], maxr_nast)); // dla i == min(i1, imaxr0 + 100) b�dzie odwo�anie do stra�nika w maxr if (w > wynik) wynik = w; } if (node > 0) { // wys�anie wyniku do serwera -------------------------------------------------------------- PutLL(0, wynik); Send(0); } else { // odebranie odpowiedzi, wyznaczenie i wypisanie najlepszego wyniku for(int odp = 0; odp < nn - 1; ++odp) { int nadawca = Receive(-1); long long w = GetLL(nadawca); if (w > wynik) wynik = w; } cout << wynik << endl; } return 0; } |