#include<stdio.h> #include<stdlib.h> #include<stdint.h> #include"message.h" using namespace std; //#define DEBUG int n,m; char *in; char *out; struct Item { int len; int sc; inline int64_t encode() { return (((int64_t)len)<<32)|sc; } inline void decode(int64_t v) { len=(int)(v>>32); sc=(int)(v&0xfffffff); } }; inline int64_t min(int64_t a, int64_t b, int64_t c) { if(a<b) { if(a<c) return a; else return c; } else { if(b<c) return b; else return c; } } Item* row1; // jeden wiersz tabeli Item* row2; // drugi wiersz tabeli Item* result; // obliczone dane do przeslania do nastepnego noda Item* input; // dane do drugiej iteracji int iter; // numer iteracji int partSize; // rozmiar porcji int from; // zakres danych od (x>=from) int to; // zakres danych do (x<to) int iterSize; // liczba wierszy dla jednej iteracji /** Metoda zamieniajaca wiersze */ void swap() { Item* tmp=row1; row1=row2; row2=tmp; } /** * Metoda obliczająca kolejny fragment tabeli * dla row2 w pozycji j zakłdając, że wszystko inne jest * gotowe */ void processFrame(int i, int j, int dif) { Item c(row1[j]); if(dif<0) { // nie ma zamiany, bez zmiany kosztu c.sc++; c.len++; } else if(dif>0) { c.len++; } Item a(row2[j]); a.len++; Item b(row1[j+1]); b.len++; row2[j+1].decode(min(c.encode(),a.encode(),b.encode())); #ifdef DEBUG //fprintf(stderr," Top item: [%d,%d]=%d.%d\n",i-1,j+1,row1[j+1].len,row1[j+1].sc); //fprintf(stderr," Left item: [%d,%d]=%d.%d\n",i,j,row2[j].len,row2[j].sc); //fprintf(stderr,"Processing item: [%d,%d]=%d.%d\n",i,j+1,row2[j+1].len,row2[j+1].sc); #endif } void singleMode() { row1=(Item*)malloc(sizeof(Item)*(m+1)); // [0..n] row2=(Item*)malloc(sizeof(Item)*(m+1)); // [0..n] for(int i=0;i<=m;++i) { row1[i].len=i; row1[i].sc=0; } for(int i=0;i<n;++i) { row2[0].len=i+1; row2[0].sc=0; for(int j=0;j<m;++j) { processFrame(i, j, (in[i]-out[j])); #ifdef DEBUG //fprintf(stderr,"Processing item: [%d,%d]=%d.%d\n",i,j+1,row2[j+1].len,row2[j+1].sc); #endif } swap(); } printf("%d %d\n",row1[m].len,row1[m].sc); } int main() { scanf("%d %d",&n,&m); in=(char*)malloc(sizeof(char)*(n+20)); out=(char*)malloc(sizeof(char)*(m+20)); Item k; k.len=5; k.sc=10; Item x=k; // odczytuję do tablicy na pozycji 1, aby było od [1..n] i [1..m]; scanf("%s %s",in,out); #ifdef DEBUG fprintf(stderr,"Readed data:\n%s\n%s\n",in,out); #endif if(((n<4000)||(m<4000))) { // dla malych danych dzialamy bez wielowatkowosci if(MyNodeId()==0) { #ifdef DEBUG fprintf(stderr,"Single node mode\n"); #endif singleMode(); } return 0; } // rozmiar jednej czesci dla danego pracownika partSize=(m/NumberOfNodes())+1; if(partSize<1000) { partSize=1000; // żeby ograniczyć ilość przesyłanych danych } // zakres od do dla danego pracownika from=MyNodeId()*partSize; to=from+partSize; iterSize=n/900; // minmalny rozmiar iteracji ze względu na ilość komunikatów if(iterSize<1000) iterSize=1000; // żeby nie były za małe porcje danych if(to>m) to=m; if(to<=from) { #ifdef DEBUG fprintf(stderr,"Not used quitting\n"); #endif return 0; // dla tego juz nie ma zadania } row1=(Item*)malloc(sizeof(Item)*(partSize+1)); // [0..partSize] row2=(Item*)malloc(sizeof(Item)*(partSize+1)); // [0..partSize] result=(Item*)malloc(sizeof(Item)*(iterSize+1)); input=(Item*)malloc(sizeof(Item)*(iterSize+1)); int partRest; if(from+partSize>m) partRest=m-from; else partRest=partSize; #ifdef DEBUG fprintf(stderr,"Processing range [%d,%d)/%d in parts %d/%d; partSize: %d (%d), numberOfNodes: %d\n", from,to,m, iterSize,n, partSize, partRest, NumberOfNodes() ); #endif // inicjujemy wiersz 0 for(int i=0;i<=partRest;++i) { row1[i].len=i+from; row1[i].sc=0; } for(iter=0;iter<n;iter+=iterSize) { int iterRest=n-iter; if(iterRest>iterSize) iterRest=iterSize; if(MyNodeId()==0) { // pierwszy komputer nie potrzebuje od kogoś danych // kolumna 0 for(int i=0;i<=iterRest;++i) { // więc je generuje input[i].len=iter+i; input[i].sc=0; } } else { // pozostali czekają na wynik od poprzednika int client=MyNodeId()-1; #ifdef DEBUG fprintf(stderr,"Waiting for data from %d\n",client); #endif #ifdef DEBUG fprintf(stderr,"Data received from %d\n",client); #endif Receive(client); for(int i=0;i<=iterRest;++i) { int64_t val=GetLL(client); input[i].decode(val); } } row1[0]=input[0]; result[0]=row1[partRest]; #ifdef DEBUG fprintf(stderr,"Processing %d/%d\n",iter,n); #endif // przetarzamy jeden fragment for(int i=0;i<iterRest;++i) { row2[0]=input[i+1]; for(int j=0;j<partRest;++j) { processFrame(i, j, (in[iter+i]-out[from+j])); } result[i+1]=row2[partRest]; swap(); } if(to<m) { // jeżeli nie ostatni to wysyłamy int server=MyNodeId()+1; for(int i=0;i<=iterRest;++i) { PutLL(server,result[i].encode()); } #ifdef DEBUG fprintf(stderr,"Sending result to %d\n",server); #endif Send(server); } } if(to==m) { // jeżeli koniec i jesteśmy ostatni to podajemy wynik printf("%d %d\n",row1[partRest].len,row1[partRest].sc); } #ifdef DEBUG fprintf(stderr,"Worker done\n"); #endif 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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | #include<stdio.h> #include<stdlib.h> #include<stdint.h> #include"message.h" using namespace std; //#define DEBUG int n,m; char *in; char *out; struct Item { int len; int sc; inline int64_t encode() { return (((int64_t)len)<<32)|sc; } inline void decode(int64_t v) { len=(int)(v>>32); sc=(int)(v&0xfffffff); } }; inline int64_t min(int64_t a, int64_t b, int64_t c) { if(a<b) { if(a<c) return a; else return c; } else { if(b<c) return b; else return c; } } Item* row1; // jeden wiersz tabeli Item* row2; // drugi wiersz tabeli Item* result; // obliczone dane do przeslania do nastepnego noda Item* input; // dane do drugiej iteracji int iter; // numer iteracji int partSize; // rozmiar porcji int from; // zakres danych od (x>=from) int to; // zakres danych do (x<to) int iterSize; // liczba wierszy dla jednej iteracji /** Metoda zamieniajaca wiersze */ void swap() { Item* tmp=row1; row1=row2; row2=tmp; } /** * Metoda obliczająca kolejny fragment tabeli * dla row2 w pozycji j zakłdając, że wszystko inne jest * gotowe */ void processFrame(int i, int j, int dif) { Item c(row1[j]); if(dif<0) { // nie ma zamiany, bez zmiany kosztu c.sc++; c.len++; } else if(dif>0) { c.len++; } Item a(row2[j]); a.len++; Item b(row1[j+1]); b.len++; row2[j+1].decode(min(c.encode(),a.encode(),b.encode())); #ifdef DEBUG //fprintf(stderr," Top item: [%d,%d]=%d.%d\n",i-1,j+1,row1[j+1].len,row1[j+1].sc); //fprintf(stderr," Left item: [%d,%d]=%d.%d\n",i,j,row2[j].len,row2[j].sc); //fprintf(stderr,"Processing item: [%d,%d]=%d.%d\n",i,j+1,row2[j+1].len,row2[j+1].sc); #endif } void singleMode() { row1=(Item*)malloc(sizeof(Item)*(m+1)); // [0..n] row2=(Item*)malloc(sizeof(Item)*(m+1)); // [0..n] for(int i=0;i<=m;++i) { row1[i].len=i; row1[i].sc=0; } for(int i=0;i<n;++i) { row2[0].len=i+1; row2[0].sc=0; for(int j=0;j<m;++j) { processFrame(i, j, (in[i]-out[j])); #ifdef DEBUG //fprintf(stderr,"Processing item: [%d,%d]=%d.%d\n",i,j+1,row2[j+1].len,row2[j+1].sc); #endif } swap(); } printf("%d %d\n",row1[m].len,row1[m].sc); } int main() { scanf("%d %d",&n,&m); in=(char*)malloc(sizeof(char)*(n+20)); out=(char*)malloc(sizeof(char)*(m+20)); Item k; k.len=5; k.sc=10; Item x=k; // odczytuję do tablicy na pozycji 1, aby było od [1..n] i [1..m]; scanf("%s %s",in,out); #ifdef DEBUG fprintf(stderr,"Readed data:\n%s\n%s\n",in,out); #endif if(((n<4000)||(m<4000))) { // dla malych danych dzialamy bez wielowatkowosci if(MyNodeId()==0) { #ifdef DEBUG fprintf(stderr,"Single node mode\n"); #endif singleMode(); } return 0; } // rozmiar jednej czesci dla danego pracownika partSize=(m/NumberOfNodes())+1; if(partSize<1000) { partSize=1000; // żeby ograniczyć ilość przesyłanych danych } // zakres od do dla danego pracownika from=MyNodeId()*partSize; to=from+partSize; iterSize=n/900; // minmalny rozmiar iteracji ze względu na ilość komunikatów if(iterSize<1000) iterSize=1000; // żeby nie były za małe porcje danych if(to>m) to=m; if(to<=from) { #ifdef DEBUG fprintf(stderr,"Not used quitting\n"); #endif return 0; // dla tego juz nie ma zadania } row1=(Item*)malloc(sizeof(Item)*(partSize+1)); // [0..partSize] row2=(Item*)malloc(sizeof(Item)*(partSize+1)); // [0..partSize] result=(Item*)malloc(sizeof(Item)*(iterSize+1)); input=(Item*)malloc(sizeof(Item)*(iterSize+1)); int partRest; if(from+partSize>m) partRest=m-from; else partRest=partSize; #ifdef DEBUG fprintf(stderr,"Processing range [%d,%d)/%d in parts %d/%d; partSize: %d (%d), numberOfNodes: %d\n", from,to,m, iterSize,n, partSize, partRest, NumberOfNodes() ); #endif // inicjujemy wiersz 0 for(int i=0;i<=partRest;++i) { row1[i].len=i+from; row1[i].sc=0; } for(iter=0;iter<n;iter+=iterSize) { int iterRest=n-iter; if(iterRest>iterSize) iterRest=iterSize; if(MyNodeId()==0) { // pierwszy komputer nie potrzebuje od kogoś danych // kolumna 0 for(int i=0;i<=iterRest;++i) { // więc je generuje input[i].len=iter+i; input[i].sc=0; } } else { // pozostali czekają na wynik od poprzednika int client=MyNodeId()-1; #ifdef DEBUG fprintf(stderr,"Waiting for data from %d\n",client); #endif #ifdef DEBUG fprintf(stderr,"Data received from %d\n",client); #endif Receive(client); for(int i=0;i<=iterRest;++i) { int64_t val=GetLL(client); input[i].decode(val); } } row1[0]=input[0]; result[0]=row1[partRest]; #ifdef DEBUG fprintf(stderr,"Processing %d/%d\n",iter,n); #endif // przetarzamy jeden fragment for(int i=0;i<iterRest;++i) { row2[0]=input[i+1]; for(int j=0;j<partRest;++j) { processFrame(i, j, (in[iter+i]-out[from+j])); } result[i+1]=row2[partRest]; swap(); } if(to<m) { // jeżeli nie ostatni to wysyłamy int server=MyNodeId()+1; for(int i=0;i<=iterRest;++i) { PutLL(server,result[i].encode()); } #ifdef DEBUG fprintf(stderr,"Sending result to %d\n",server); #endif Send(server); } } if(to==m) { // jeżeli koniec i jesteśmy ostatni to podajemy wynik printf("%d %d\n",row1[partRest].len,row1[partRest].sc); } #ifdef DEBUG fprintf(stderr,"Worker done\n"); #endif return 0; } |