/*
* Copyright (C) 2014 Paweł Widera
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
* http://www.gnu.org/licenses/gpl.html
*/
#include "maklib.h"
#include "message.h"
#include <tuple>
#include <cmath>
#include <iostream>
using namespace std;
tuple<long long int, int, int> find_max_sum(int a, int b) {
long long int max_sum = 0;
long long int sum = 0;
int begin = a;
int end = b;
//cout << "a,b " << a << " " << b << endl;
for (auto i = a; i < b; ++i) {
if (sum > 0) {
sum += ElementAt(i);
} else {
sum = ElementAt(i);
begin = i;
}
if (sum > max_sum) {
max_sum = sum;
end = i + 1;
}
}
// enable skipping the fragment if all numbers are negative
if (0 == max_sum) {
begin = end;
}
return make_tuple(max_sum, begin, end);
}
int main() {
int fragment_size = ceil(Size() / float(NumberOfNodes()));
long long int max_sum;
int begin;
int end;
tie(max_sum, begin, end) = find_max_sum(MyNodeId() * fragment_size + 1,
min((MyNodeId() + 1) * fragment_size + 1, Size() + 1));
//cout << max_sum << " " << begin << "," << end << endl;
if (MyNodeId() > 0) {
PutLL(0, max_sum);
PutInt(0, begin);
PutInt(0, end);
Send(0);
} else {
auto sum = max_sum;
for (int k = 1; k < NumberOfNodes(); ++k) {
Receive(k);
auto next_max_sum = GetLL(k);
auto next_begin = GetInt(k);
auto next_end = GetInt(k);
//cout << "merge " << next_begin << "," << next_end << endl;
// merge current and next fragment
for (int i = end; i < next_begin; ++i) {
if (sum > 0) {
sum += ElementAt(i);
} else {
// skip if all numbers in the fragment are negative
if (0 == next_max_sum) {
break;
} else {
sum = ElementAt(i);
}
}
if (sum > max_sum) {
max_sum = sum;
}
}
//cout << "merge sum = " << sum << endl;
if (sum > 0) {
sum += next_max_sum;
} else {
sum = next_max_sum;
}
if (sum >= max_sum) {
max_sum = sum;
}
//cout << "merge max_sum = " << max_sum << endl;
end = next_end;
}
if (max_sum < 0) {
max_sum = 0;
}
cout << max_sum << 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 | /* * Copyright (C) 2014 Paweł Widera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * http://www.gnu.org/licenses/gpl.html */ #include "maklib.h" #include "message.h" #include <tuple> #include <cmath> #include <iostream> using namespace std; tuple<long long int, int, int> find_max_sum(int a, int b) { long long int max_sum = 0; long long int sum = 0; int begin = a; int end = b; //cout << "a,b " << a << " " << b << endl; for (auto i = a; i < b; ++i) { if (sum > 0) { sum += ElementAt(i); } else { sum = ElementAt(i); begin = i; } if (sum > max_sum) { max_sum = sum; end = i + 1; } } // enable skipping the fragment if all numbers are negative if (0 == max_sum) { begin = end; } return make_tuple(max_sum, begin, end); } int main() { int fragment_size = ceil(Size() / float(NumberOfNodes())); long long int max_sum; int begin; int end; tie(max_sum, begin, end) = find_max_sum(MyNodeId() * fragment_size + 1, min((MyNodeId() + 1) * fragment_size + 1, Size() + 1)); //cout << max_sum << " " << begin << "," << end << endl; if (MyNodeId() > 0) { PutLL(0, max_sum); PutInt(0, begin); PutInt(0, end); Send(0); } else { auto sum = max_sum; for (int k = 1; k < NumberOfNodes(); ++k) { Receive(k); auto next_max_sum = GetLL(k); auto next_begin = GetInt(k); auto next_end = GetInt(k); //cout << "merge " << next_begin << "," << next_end << endl; // merge current and next fragment for (int i = end; i < next_begin; ++i) { if (sum > 0) { sum += ElementAt(i); } else { // skip if all numbers in the fragment are negative if (0 == next_max_sum) { break; } else { sum = ElementAt(i); } } if (sum > max_sum) { max_sum = sum; } } //cout << "merge sum = " << sum << endl; if (sum > 0) { sum += next_max_sum; } else { sum = next_max_sum; } if (sum >= max_sum) { max_sum = sum; } //cout << "merge max_sum = " << max_sum << endl; end = next_end; } if (max_sum < 0) { max_sum = 0; } cout << max_sum << endl; } return 0; } |
English