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
#include "krazki.h"
#include "message.h"
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int main() {
    int n = PipeHeight();
    int m = NumberOfDiscs();

    vector<long long int> mins;

    int id = MyNodeId();
    int instances = NumberOfNodes();
    int pipesPerInstance;

    if (n <= instances) {
        pipesPerInstance = 1;
        instances = n;
    } else if (n % instances == 0) {
        pipesPerInstance = n/instances;
    } else {
        pipesPerInstance = 1 + n/instances;
        if (n % pipesPerInstance == 0) {
            instances = n / pipesPerInstance;
        } else {
            instances = 1 + n/pipesPerInstance;
        }
    }

    if (id >= instances) {
        return 0;
    }

    int firstPipe = id * pipesPerInstance;

    mins.resize(pipesPerInstance);

    mins[0] = HoleDiameter(firstPipe + 1);
    int i = 1;

    for (; (i < pipesPerInstance) && (i + firstPipe < n); ++i) {
        mins[i] = min(mins[i - 1], HoleDiameter(i + firstPipe + 1));
    }
    //i is after last pipe for instance

    long long int prev_inst_min;
    int j;
    if (id > 0) {
        Receive(id - 1);
        prev_inst_min = GetLL(id - 1);
        j = 0;
        while (j < i && prev_inst_min < mins[j]) {
            mins[j] = prev_inst_min;
            ++j;
        }
    }

    if (id < instances - 1) {
        PutLL(id + 1, mins[i - 1]);
        Send(id + 1);
    }

    int k;
    int global_level = n;

    if (id < instances-1) {
    	Receive(id + 1);
    	k = GetInt(id + 1);
    	global_level = GetInt(id + 1);
    } else {
    	k = 0;
    }

	long long int discDiameter;
	int current_level = i - 1;
	bool stop = false;

	while(!stop && k < m) {
		discDiameter = DiscDiameter(k + 1);
    	while(current_level >= 0 && discDiameter > mins[current_level]) {
    		--current_level;
    		--global_level;
    	}

    	if (current_level < 0) {
    		//przepelniony
    		stop = true;
            
            if(id > 0) {
    		  PutInt(id - 1, k);
    		  PutInt(id - 1, global_level);
    		  Send(id - 1);
    		  return 0;
            }
    	} else {
    		//wejdzie, bierzemy nastepny dysk
    		--current_level;
    		--global_level;
    		++k;
    	}
	}

	if (id > 0) {
		PutInt(id - 1, k);
		PutInt(id - 1, global_level);
		Send(id - 1);
	} else {
		if (k >= m) {
			cout << global_level + 1;
		} else {
			//nie wszystko weszlo
			cout << 0;
		}
	}

    return 0;
}