#include <iostream> #include "message.h" #include "teatr.h" using namespace std; /* ratunkowa wersja minimum */ struct TheaterPart { long long quarrels; long long persons[5]; }; TheaterPart mergeParts(const TheaterPart& one, const TheaterPart& two) { TheaterPart result; result.quarrels = one.quarrels + two.quarrels; for (int i2 = 0; i2 < 4; ++i2) { for (int i1 = i2 + 1; i1 < 5; ++i1) { result.quarrels += two.persons[i2] * one.persons[i1]; } } for (int i = 0; i < 5; ++i) { result.persons[i] = one.persons[i] + two.persons[i]; } return result; } TheaterPart calculatePart(long long start, long long size, bool regularSize) { TheaterPart result; if (size == 1) { int height = GetElement(start); result.quarrels = 0; for (int i=0; i < 5; ++i) { result.persons[i] = 0; } result.persons[height - 1] = 1; return result; } TheaterPart one, two; if (regularSize) { long long halfSize = size / 2; one = calculatePart(start, halfSize, true); two = calculatePart(start + halfSize, halfSize, true); } else { long long oneSize = 1; while (oneSize < size) { oneSize = oneSize * 2; } oneSize = oneSize / 2; one = calculatePart(start, oneSize, true); two = calculatePart(start + oneSize, size - oneSize, false); } result = mergeParts(one, two); return result; } int main() { /* Node 0 is master. Other nodes are slave. Every slave wait for two numbers (start, size) and do: * calculatePart(start, size), * send (quarrels, persons[0] ... persons[4]) to master, * finish work. If slave receive (0, 0) imediately finish work. If N < 100 * NumberOfNodes only master resolve problem. Master send to slaves two numbers (0,0) and resolve all. If N is bigger master divide problem for all nodes and send to slaves (start, size). Later resolve one part and wait for responses from slaves. Finaly merge results. */ if (MyNodeId() == 0) { int numberOfNodes = NumberOfNodes(); int lastNode = numberOfNodes - 1; long long n = GetN(); if (n < 100 * numberOfNodes) { for (int i = 1; i < numberOfNodes; i++) { PutLL(i, 0); PutLL(i, 0); Send(i); } TheaterPart result; result = calculatePart(0, n, false); cout << result.quarrels; } else { long long size = n / numberOfNodes; long long start = size; for (int i = 1; i < lastNode; i++) { PutLL(i, start); PutLL(i, size); Send(i); start = start + size; } PutLL(lastNode, start); PutLL(lastNode, n - start); Send(lastNode); TheaterPart result; result = calculatePart(0, size, false); TheaterPart newPart; for (int i = 1; i < numberOfNodes; i++) { Receive(i); newPart.quarrels = GetLL(i); for (int j=0; j <5; ++j) { newPart.persons[j] = GetLL(i); } result = mergeParts(result, newPart); } cout << result.quarrels; } } else { Receive(0); long long start = GetLL(0); long long size = GetLL(0); if (size > 0) { TheaterPart result; result = calculatePart(start, size, false); PutLL(0, result.quarrels); for (int j=0; j <5; ++j) { PutLL(0, result.persons[j]); } Send(0); } } 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 | #include <iostream> #include "message.h" #include "teatr.h" using namespace std; /* ratunkowa wersja minimum */ struct TheaterPart { long long quarrels; long long persons[5]; }; TheaterPart mergeParts(const TheaterPart& one, const TheaterPart& two) { TheaterPart result; result.quarrels = one.quarrels + two.quarrels; for (int i2 = 0; i2 < 4; ++i2) { for (int i1 = i2 + 1; i1 < 5; ++i1) { result.quarrels += two.persons[i2] * one.persons[i1]; } } for (int i = 0; i < 5; ++i) { result.persons[i] = one.persons[i] + two.persons[i]; } return result; } TheaterPart calculatePart(long long start, long long size, bool regularSize) { TheaterPart result; if (size == 1) { int height = GetElement(start); result.quarrels = 0; for (int i=0; i < 5; ++i) { result.persons[i] = 0; } result.persons[height - 1] = 1; return result; } TheaterPart one, two; if (regularSize) { long long halfSize = size / 2; one = calculatePart(start, halfSize, true); two = calculatePart(start + halfSize, halfSize, true); } else { long long oneSize = 1; while (oneSize < size) { oneSize = oneSize * 2; } oneSize = oneSize / 2; one = calculatePart(start, oneSize, true); two = calculatePart(start + oneSize, size - oneSize, false); } result = mergeParts(one, two); return result; } int main() { /* Node 0 is master. Other nodes are slave. Every slave wait for two numbers (start, size) and do: * calculatePart(start, size), * send (quarrels, persons[0] ... persons[4]) to master, * finish work. If slave receive (0, 0) imediately finish work. If N < 100 * NumberOfNodes only master resolve problem. Master send to slaves two numbers (0,0) and resolve all. If N is bigger master divide problem for all nodes and send to slaves (start, size). Later resolve one part and wait for responses from slaves. Finaly merge results. */ if (MyNodeId() == 0) { int numberOfNodes = NumberOfNodes(); int lastNode = numberOfNodes - 1; long long n = GetN(); if (n < 100 * numberOfNodes) { for (int i = 1; i < numberOfNodes; i++) { PutLL(i, 0); PutLL(i, 0); Send(i); } TheaterPart result; result = calculatePart(0, n, false); cout << result.quarrels; } else { long long size = n / numberOfNodes; long long start = size; for (int i = 1; i < lastNode; i++) { PutLL(i, start); PutLL(i, size); Send(i); start = start + size; } PutLL(lastNode, start); PutLL(lastNode, n - start); Send(lastNode); TheaterPart result; result = calculatePart(0, size, false); TheaterPart newPart; for (int i = 1; i < numberOfNodes; i++) { Receive(i); newPart.quarrels = GetLL(i); for (int j=0; j <5; ++j) { newPart.persons[j] = GetLL(i); } result = mergeParts(result, newPart); } cout << result.quarrels; } } else { Receive(0); long long start = GetLL(0); long long size = GetLL(0); if (size > 0) { TheaterPart result; result = calculatePart(start, size, false); PutLL(0, result.quarrels); for (int j=0; j <5; ++j) { PutLL(0, result.persons[j]); } Send(0); } } return 0; } |