#include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include "krazki.h" #include "message.h" int main() { long long int nodes = NumberOfNodes(); long long int id = MyNodeId(); long long int height = PipeHeight(); long long int discs = NumberOfDiscs(); long long int top = height * id / nodes + 1; long long int bottom = height * (id+1) / nodes; long long int first = discs * id / nodes + 1; long long int last = (id+1) * discs / nodes; long long int *pipeSize = new long long int[bottom-top+10]; //calc min pipe diameter long long int startMinPipeDiameter = std::numeric_limits<long long int>::max(); long long int minPipeDiameter = std::numeric_limits<long long int>::max(); for (long long int h=top; h<=bottom; h++) { pipeSize[h-top] = minPipeDiameter = std::min(minPipeDiameter, HoleDiameter(h)); } //calc max disc diameter long long int startMaxDiscDiameter = 0; long long int maxDiscDiameter = 0; for (long long int h=first; h<=last; h++) { maxDiscDiameter = std::max(maxDiscDiameter, DiscDiameter(h)); } if (id>0) { Receive(id-1); startMinPipeDiameter = GetLL(id-1); startMaxDiscDiameter = GetLL(id-1); } if (id+1<nodes) { PutLL(id+1, std::min(startMinPipeDiameter,minPipeDiameter)); PutLL(id+1, std::max(startMaxDiscDiameter,maxDiscDiameter)); Send(id+1); } //calc position of disc diameter std::vector<std::pair<long long int, long long int> > discDiameters; discDiameters.push_back(std::make_pair(0,0)); for (int i=0; i<nodes; ++i) { if (i!=id) { PutLL(i, last); PutLL(i, std::max(startMaxDiscDiameter,maxDiscDiameter)); Send(i); } } for (int i=0; i<nodes; ++i) { if (i!=id) { Receive(i); long long int pos = GetLL(i); long long int val = GetLL(i); discDiameters.push_back(std::make_pair(pos,val)); } else { discDiameters.push_back(std::make_pair(last, std::max(startMaxDiscDiameter,maxDiscDiameter))); } } //find first disc > startMinPipeDiameter long long int minValue = std::min(startMinPipeDiameter, minPipeDiameter); long long int start = discDiameters[nodes].first; long long int size = discDiameters[nodes].second; for (size_t i=1; i<=nodes; ++i) { if (discDiameters[i].second > minValue) { start = discDiameters[i-1].first; size = discDiameters[i-1].second; break; } } start = std::max(start,1LL); while (start<=discs) { size = std::max(size, DiscDiameter(start)); if (size>minValue) break; start++; } //fill long long int current = start; long long int holes = 0; long long int bholes = 0; long long int lused = height+1; for (long long int h=bottom; h>=top; h--) { if (current<=discs && std::min(startMinPipeDiameter,pipeSize[h-top]) >= size) { current++; if (current<=discs) size = std::max(size, DiscDiameter(current)); lused = h; bholes = holes; } else { holes++; } } //join long long int finish,pos; if (id+1<nodes) { Receive(id+1); finish = GetLL(id+1); //first free disc pos = GetLL(id+1); //last used pos } else { finish = 1; pos = height+1; } if (current==start) { long long int touse = std::min(start-finish, holes); if (touse > 0) { finish += touse; lused = bottom-touse+1; } else { finish = finish; lused = pos; } } else { if (start-finish > holes) { finish = finish + (bottom-top+1); lused = top; } else { lused -= (start-finish-bholes>0)?(start-finish-bholes):0; finish = current; } } if (id>0) { PutLL(id-1, finish); PutLL(id-1, lused); Send(id-1); } if (id==0) { printf("%lld\n",(finish==discs+1)?lused:0); } return EXIT_SUCCESS; }
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 | #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include "krazki.h" #include "message.h" int main() { long long int nodes = NumberOfNodes(); long long int id = MyNodeId(); long long int height = PipeHeight(); long long int discs = NumberOfDiscs(); long long int top = height * id / nodes + 1; long long int bottom = height * (id+1) / nodes; long long int first = discs * id / nodes + 1; long long int last = (id+1) * discs / nodes; long long int *pipeSize = new long long int[bottom-top+10]; //calc min pipe diameter long long int startMinPipeDiameter = std::numeric_limits<long long int>::max(); long long int minPipeDiameter = std::numeric_limits<long long int>::max(); for (long long int h=top; h<=bottom; h++) { pipeSize[h-top] = minPipeDiameter = std::min(minPipeDiameter, HoleDiameter(h)); } //calc max disc diameter long long int startMaxDiscDiameter = 0; long long int maxDiscDiameter = 0; for (long long int h=first; h<=last; h++) { maxDiscDiameter = std::max(maxDiscDiameter, DiscDiameter(h)); } if (id>0) { Receive(id-1); startMinPipeDiameter = GetLL(id-1); startMaxDiscDiameter = GetLL(id-1); } if (id+1<nodes) { PutLL(id+1, std::min(startMinPipeDiameter,minPipeDiameter)); PutLL(id+1, std::max(startMaxDiscDiameter,maxDiscDiameter)); Send(id+1); } //calc position of disc diameter std::vector<std::pair<long long int, long long int> > discDiameters; discDiameters.push_back(std::make_pair(0,0)); for (int i=0; i<nodes; ++i) { if (i!=id) { PutLL(i, last); PutLL(i, std::max(startMaxDiscDiameter,maxDiscDiameter)); Send(i); } } for (int i=0; i<nodes; ++i) { if (i!=id) { Receive(i); long long int pos = GetLL(i); long long int val = GetLL(i); discDiameters.push_back(std::make_pair(pos,val)); } else { discDiameters.push_back(std::make_pair(last, std::max(startMaxDiscDiameter,maxDiscDiameter))); } } //find first disc > startMinPipeDiameter long long int minValue = std::min(startMinPipeDiameter, minPipeDiameter); long long int start = discDiameters[nodes].first; long long int size = discDiameters[nodes].second; for (size_t i=1; i<=nodes; ++i) { if (discDiameters[i].second > minValue) { start = discDiameters[i-1].first; size = discDiameters[i-1].second; break; } } start = std::max(start,1LL); while (start<=discs) { size = std::max(size, DiscDiameter(start)); if (size>minValue) break; start++; } //fill long long int current = start; long long int holes = 0; long long int bholes = 0; long long int lused = height+1; for (long long int h=bottom; h>=top; h--) { if (current<=discs && std::min(startMinPipeDiameter,pipeSize[h-top]) >= size) { current++; if (current<=discs) size = std::max(size, DiscDiameter(current)); lused = h; bholes = holes; } else { holes++; } } //join long long int finish,pos; if (id+1<nodes) { Receive(id+1); finish = GetLL(id+1); //first free disc pos = GetLL(id+1); //last used pos } else { finish = 1; pos = height+1; } if (current==start) { long long int touse = std::min(start-finish, holes); if (touse > 0) { finish += touse; lused = bottom-touse+1; } else { finish = finish; lused = pos; } } else { if (start-finish > holes) { finish = finish + (bottom-top+1); lused = top; } else { lused -= (start-finish-bholes>0)?(start-finish-bholes):0; finish = current; } } if (id>0) { PutLL(id-1, finish); PutLL(id-1, lused); Send(id-1); } if (id==0) { printf("%lld\n",(finish==discs+1)?lused:0); } return EXIT_SUCCESS; } |