#include <iostream> #include <vector> #include <algorithm> #include "message.h" #include "maklib.h" class INodeRunner { public: virtual void Run() = 0; }; struct AnalyseRequest { long long beginIndex; long long endIndex; }; struct AnalyseResult { long long maxSum; long long maxSumFromBeginning; long long lastRangeSum; }; struct NodeAnalyseResult { int nodeId; AnalyseResult result; }; class MergeNodeRunner: public INodeRunner { public: void Run() { int numberOfWorkingNodes = NumberOfNodes() - 1; //from 10 to 100 long long tableSize = Size(); _results.resize(numberOfWorkingNodes); SendAnalyseRequests(numberOfWorkingNodes, tableSize); for(int i = 0; i < numberOfWorkingNodes; ++i) { auto nodeResult = ReceiveNodeResult(); _results[nodeResult.nodeId - 1] = nodeResult.result; } long long maxSum = GetMaxSum(); std::cout << maxSum; } private: long long GetMaxSum() { long long maxSum = _results[0].maxSum; long long lastRangeSum = 0; for(auto i = 1; i < _results.size(); ++i) { auto& res = _results[i]; auto newSum = std::max(res.maxSum, res.maxSumFromBeginning + lastRangeSum); if(newSum > maxSum) maxSum = newSum; lastRangeSum = res.lastRangeSum; } return maxSum; } NodeAnalyseResult ReceiveNodeResult() { NodeAnalyseResult res; res.nodeId = Receive(-1); res.result.maxSum = GetLL(res.nodeId); res.result.maxSumFromBeginning = GetLL(res.nodeId); res.result.lastRangeSum = GetLL(res.nodeId); return res; } void SendAnalyseRequests(int numberOfNodes, long long tableSize) { int numberOfCalculateNodes = numberOfNodes; long long elementsPerNode = tableSize / (numberOfNodes - 1); long long currIdx = 0; int targetId = 1; while(tableSize > 0) { AnalyseRequest req; req.beginIndex = currIdx + 1; if(tableSize < elementsPerNode) { elementsPerNode = tableSize; } req.endIndex = currIdx + elementsPerNode; SendRequest(req, targetId); currIdx = currIdx + elementsPerNode; tableSize -= elementsPerNode; ++targetId; } } void SendRequest(AnalyseRequest request, int targetId) { PutLL(targetId, request.beginIndex); PutLL(targetId, request.endIndex); Send(targetId); } std::vector<AnalyseResult> _results; }; class SearcherNodeRunner: public INodeRunner { static const int MergeNodeId = 0; public: void Run() { auto req = ReceiveAnalyseRequest(); auto resp = CalculateResult(req); SendResponse(resp); } private: AnalyseResult CalculateResult(AnalyseRequest request) { AnalyseResult res; long long elem = ElementAt(request.beginIndex); res.maxSum = elem; res.maxSumFromBeginning = elem; auto total = elem; long long currMaxSum = elem; for(long long i = request.beginIndex + 1; i <= request.endIndex; ++i) { long long elem = ElementAt(i); total += elem; if(elem > currMaxSum + elem) //start new sub table currMaxSum = elem; else //continue last sum currMaxSum = currMaxSum + elem; if(currMaxSum > res.maxSum) { res.maxSum = currMaxSum; } if(total > res.maxSumFromBeginning) res.maxSumFromBeginning = total; } res.lastRangeSum = currMaxSum; return res; } void SendResponse(AnalyseResult resp) { PutLL(MergeNodeId, resp.maxSum); PutLL(MergeNodeId, resp.maxSumFromBeginning); PutLL(MergeNodeId, resp.lastRangeSum); Send(MergeNodeId); } AnalyseRequest ReceiveAnalyseRequest() { Receive(MergeNodeId); AnalyseRequest request; request.beginIndex = GetLL(MergeNodeId); request.endIndex = GetLL(MergeNodeId); return request; } }; int main() { INodeRunner* runner; if(MyNodeId() == 0) runner = new MergeNodeRunner(); else runner = new SearcherNodeRunner(); runner->Run(); delete runner; }
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 | #include <iostream> #include <vector> #include <algorithm> #include "message.h" #include "maklib.h" class INodeRunner { public: virtual void Run() = 0; }; struct AnalyseRequest { long long beginIndex; long long endIndex; }; struct AnalyseResult { long long maxSum; long long maxSumFromBeginning; long long lastRangeSum; }; struct NodeAnalyseResult { int nodeId; AnalyseResult result; }; class MergeNodeRunner: public INodeRunner { public: void Run() { int numberOfWorkingNodes = NumberOfNodes() - 1; //from 10 to 100 long long tableSize = Size(); _results.resize(numberOfWorkingNodes); SendAnalyseRequests(numberOfWorkingNodes, tableSize); for(int i = 0; i < numberOfWorkingNodes; ++i) { auto nodeResult = ReceiveNodeResult(); _results[nodeResult.nodeId - 1] = nodeResult.result; } long long maxSum = GetMaxSum(); std::cout << maxSum; } private: long long GetMaxSum() { long long maxSum = _results[0].maxSum; long long lastRangeSum = 0; for(auto i = 1; i < _results.size(); ++i) { auto& res = _results[i]; auto newSum = std::max(res.maxSum, res.maxSumFromBeginning + lastRangeSum); if(newSum > maxSum) maxSum = newSum; lastRangeSum = res.lastRangeSum; } return maxSum; } NodeAnalyseResult ReceiveNodeResult() { NodeAnalyseResult res; res.nodeId = Receive(-1); res.result.maxSum = GetLL(res.nodeId); res.result.maxSumFromBeginning = GetLL(res.nodeId); res.result.lastRangeSum = GetLL(res.nodeId); return res; } void SendAnalyseRequests(int numberOfNodes, long long tableSize) { int numberOfCalculateNodes = numberOfNodes; long long elementsPerNode = tableSize / (numberOfNodes - 1); long long currIdx = 0; int targetId = 1; while(tableSize > 0) { AnalyseRequest req; req.beginIndex = currIdx + 1; if(tableSize < elementsPerNode) { elementsPerNode = tableSize; } req.endIndex = currIdx + elementsPerNode; SendRequest(req, targetId); currIdx = currIdx + elementsPerNode; tableSize -= elementsPerNode; ++targetId; } } void SendRequest(AnalyseRequest request, int targetId) { PutLL(targetId, request.beginIndex); PutLL(targetId, request.endIndex); Send(targetId); } std::vector<AnalyseResult> _results; }; class SearcherNodeRunner: public INodeRunner { static const int MergeNodeId = 0; public: void Run() { auto req = ReceiveAnalyseRequest(); auto resp = CalculateResult(req); SendResponse(resp); } private: AnalyseResult CalculateResult(AnalyseRequest request) { AnalyseResult res; long long elem = ElementAt(request.beginIndex); res.maxSum = elem; res.maxSumFromBeginning = elem; auto total = elem; long long currMaxSum = elem; for(long long i = request.beginIndex + 1; i <= request.endIndex; ++i) { long long elem = ElementAt(i); total += elem; if(elem > currMaxSum + elem) //start new sub table currMaxSum = elem; else //continue last sum currMaxSum = currMaxSum + elem; if(currMaxSum > res.maxSum) { res.maxSum = currMaxSum; } if(total > res.maxSumFromBeginning) res.maxSumFromBeginning = total; } res.lastRangeSum = currMaxSum; return res; } void SendResponse(AnalyseResult resp) { PutLL(MergeNodeId, resp.maxSum); PutLL(MergeNodeId, resp.maxSumFromBeginning); PutLL(MergeNodeId, resp.lastRangeSum); Send(MergeNodeId); } AnalyseRequest ReceiveAnalyseRequest() { Receive(MergeNodeId); AnalyseRequest request; request.beginIndex = GetLL(MergeNodeId); request.endIndex = GetLL(MergeNodeId); return request; } }; int main() { INodeRunner* runner; if(MyNodeId() == 0) runner = new MergeNodeRunner(); else runner = new SearcherNodeRunner(); runner->Run(); delete runner; } |