您的位置:首页 > 编程语言

《编程之美》读书随笔之七:光影切割问题

2013-12-10 10:00 232 查看
最近赶项目,编程之美也落下好长时间了,今天看了编程之美中的光影切割问题,感悟挺多,觉得无论什么几何上的问题,都能转换成很简单程序去解决。

题目就不说了,还要画图比较麻烦,有兴趣的可以看看这本书(不是在打广告),废话不多说了,进入正题:

通过书上的分析,可以看出这个题也就是求出所有直线两两直线的交点,然后再查找哪些在这两个平面之间,也就是在这两面墙之间。书上介绍的方法有两种,第二种方法有多种解法,我暂时没有想到有什么其他的方式。

第一种方法:

第一种方法比较简单,就是对计算所有点的过程,这里涉及到一些几何交点的求法,暂时不写了,然后对没个交点按X轴进行排序,求出在两个平面之间的个数N,再根据书上介绍的公式求出平面被分割的块数。但是我觉得不需要排序,直接遍历这个数组,计算没个元素是否在两个平面之间,然后计算在平面之间的点的个数就OK了,不知道书上为什么要先排序,再查找,这个明显提高了空间和时间复杂度。

第二种方法:

第二种方法比较神奇,当然再神奇也是有数学根据的,通过书上的分析可以知道,区域内的交点个数等于一个边界上交点顺序相对于另一个边界交点顺序的逆序数的和,现在的问题就转化成求一个数组的逆序数,这样对问题再次进行了转化。

下面是两种求逆序数的方法,第一个是直接遍历数组,求出逆序数,时间复杂度是O(N^2),第二种的时间复杂度是O(N*log2N)。

第一种算法:

int inverseCount(int *origNumber, int Num)
{
int count = 0;
for(int i = 0; i < Num-1; i++)
{
int temp = origNumber[i];
for(int j = i+1; j < Num; j++)
{
if(temp > origNumber[j])count++;
}
}
return count;
}


第二种算法:

const int LENGTH=100;
int temp[LENGTH];  //额外的辅助数组

int count=0;

void Merge(int * array,int first,int med,int last)
{
int i=first,j=med+1;
int cur=0;
while (i<=med&&j<=last)
{
if (array[i]<array[j])
{
temp[cur++]=array[i++];
}
else
{
temp[cur++]=array[j++];
count+=med-i+1;  //核心代码,逆序数增加
}
}
while (i<=med)
{
temp[cur++]=array[i++];
}
while (j<=last)
{
temp[cur++]=array[j++];
}
for (int m=0;m<cur;m++)
{
array[first++]=temp[m];
}
}
void MergeSort(int *array,int first,int last)
{
if (first==last)
{
return ;
}
int med=first+(last-first)/2;
MergeSort(array,first,med);
MergeSort(array,med+1,last);
Merge(array,first,med,last);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: