Думаю, я бы начал со следующего, что близко к тому, что @belisarius уже предлагал. Если у вас есть какие-либо дополнительные требования, такие как предпочтение «почти квадратных» прямоугольников, а не «длинных и тонких», вам нужно изменить этот наивный подход. Для простоты я предполагаю, что точки распределены приблизительно случайным образом.
- Разделите ваш начальный прямоугольник на 2 с линией, параллельной короткой стороне прямоугольника и проходящей точно через середину.
- Подсчитайте количество точек в обоих полуугольниках. Если они равны (достаточно), перейдите к шагу 4. В противном случае перейдите к шагу 3.
- Исходя из распределения точек между полупрямоугольниками, переместите линию, чтобы выровнять вещи снова. Так что, если, вероятно, первый разрез разделит точки 1/3, 2/3, переместите линию на полпути в тяжелую половину прямоугольника. Перейдите к шагу 2. (Будьте осторожны, чтобы не оказаться здесь в ловушке, перемещая линию постепенно уменьшающимися шагами сначала в одном направлении, а затем в другом.)
- Теперь передайте каждый из полупрямоугольников рекурсивному вызову этой функции на шаге 1.
Надеюсь, это достаточно хорошо описывает предложение. У него есть ограничения: он будет производить количество прямоугольников, равное некоторой степени 2, поэтому отрегулируйте его, если этого недостаточно. Я сформулировал это рекурсивно, но он идеально подходит для распараллеливания. Каждое разделение создает две задачи, каждая из которых разбивает прямоугольник и создает еще две задачи.
Если вам не нравится такой подход, возможно, вы могли бы начать с регулярной сетки с некоторым кратным (возможно, 10 - 100) количеством желаемых прямоугольников. Подсчитайте количество точек в каждом из этих крошечных прямоугольников. Затем начните склеивать крошечные прямоугольники вместе, пока менее крошечный прямоугольник не содержит (приблизительно) нужное количество точек. Или, если он удовлетворяет вашим требованиям достаточно хорошо, вы можете использовать это как метод дискретизации и интегрировать его с моим первым подходом, но размещать линии разреза только вдоль границ крошечных прямоугольников. Вероятно, это будет гораздо быстрее, поскольку вам нужно будет только посчитать точки в каждом крошечном прямоугольнике один раз.
Я действительно не задумывался о времени работы любого из них; Я предпочитаю первый подход, потому что я занимаюсь большим количеством параллельного программирования и имею кучу процессоров.