2
ewertЦитата:
Кстати, наиболее простой способ машинного подсчёта -- это просто тупой перебор всех целочисленных точек с отбраковкой тех, которые не удовлетворяют ограничениям (полный аналог ручного подсчёта по картинке на плоскости). Казалось бы, способ неэффективный, но это ещё как сказать.
Набросал на C наикривейший (но все-таки быстрый) brute-force алгоритмик подсчета целочисленных точек в произвольном гиперпространственном полиэдре, заданным набором неравенств (de-facto сканируется пересечение полиэдра с фиксированным положительным гиперкубом):
Код:
#include <stdio.h>
/* Auxiliary definitions. */
#define Begin_System \
int Inequality \
(int Number, int *x) \
{switch(Number){
#define End_System \
default: printf("Error!"); \
return 0;}}
#define Entry(n) case n: return
/* Space dimension. */
#define Inequalities 2
/*
** Size of the scan area
** (side of the hypercube).
*/
const Cube=100;
/*
** System of inequalities.
**
** To add inequality use syntax
** Entry(<inequality number>) inequality;
**
** All variables stored in
** zero-based array x.
*/
Begin_System
Entry(0) x[1] >= 2*x[0]-4;
Entry(1) x[1] <= -3*x[0]+40-3*x[1];
End_System
/*
** Generates next integer point.
*/
int NextPoint(int *Vector)
{
int Counter=0;
do
if(Vector[Counter]==Cube)
Vector[Counter]=0;
else
{
Vector[Counter]++;
return 1;
}
while(++Counter<Inequalities);
return 0;
}
int main(void)
{
int
Vector[Inequalities]={0},
Counter,
IntegerFlag,
Result=0;
printf("Scanning...\n");
/*
** Scan through the hypercube and
** count integer points satisfying
** inequalities defined above
** (i.e. points inside polyhedra,
** defined by this conditions).
*/
do
{
for
(
Counter=0,IntegerFlag=1;
Counter<Inequalities;
Counter++
)
if(!Inequality(Counter,Vector)) IntegerFlag=0;
if(IntegerFlag) Result++;
}
while(NextPoint(Vector));
printf
(
"Count of integer points "
"in given polyhedra is %d.",
Result
);
return 0;
}
В данном случае, эта программулька решает исходную задачу, поставленную
LaraKroft. Кстати, ответ равен 41.
-- Вт авг 11, 2009 05:30:20 --Только что до меня дошло, что этот код может работать не только с многогранниками, но и вообще с любыми ограниченными телами, задающимися системами неравенств (необязательно линейных). Эти области могут быть и невыпуклыми и даже многосвязными.
Цитата:
Манипуляции с целыми частями всё равно подразумевают перебор по всем переменным, кроме одной, т.е. порядка
операций, где
-- количество точек по каждой переменной и
-- размерность задачи. А прямой перебор требует порядка
операций, не так уж и намного больше.
Можно сканировать область прыгающими по целочисленной сетке параллельными прямыми исходя из соображения о том, что пересечение области с прямой суть набор отрезков, по длинам и смещениям которых можно подсчитывать целые точки.
В этом случае сложность будет порядка
, где
-- оценка сложности определения пересечений прямой с границей области. Улучшение асимптотического поведения алгоритма будет наблюдаться если детектирование пересечений будет значительно дешевле чем
, но даже при максимальной сложности можно ожидать прироста производительности если хотя бы детектировать за константное время промахи трассировки мимо обмеряемой области.
-- Вт авг 11, 2009 05:51:40 --Наткнулся на родственную соседнюю тему
Как посчитать количество целых точек в многограннике? Там есть интересные ссылочки.