HDU2050 折线分割平面

来源:互联网 发布:js判断质数的算法 编辑:程序博客网 时间:2024/05/17 01:38

我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目。比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分,具体如下所示。
 

Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C 行数据,每行包含一个整数n(0<n<=10000),表示折线的数量。

 

Output
对于每个测试实例,请输出平面的最大分割数,每个实例的输出占一行。

 

Sample Input
212
 

Sample Output
27


这种类型的题目,在acm编程中比较经典,这里我们由浅入深来学习下:
(1)在一个平面上有一个圆和n条直线,这些直线中每一条在圆内同其他直线相交,假设没有3条直线相

交于一点,试问这些直线将圆分成多少区域。
很容易看出递推关系,每新增一条直线,都将原来所有的区域分成两半,因此第n条直线会在原来的基础

上再添加n个平面,函数递推关系式如下:

递推公式1:

f(0) = 1
f(1) = 2
f(2) = 4
...
f(n) = f(n - 1) + n

通项公式推导1:

f(n)
= f(n - 1) + n
= f(n - 2) + n + (n - 1)
= ...
= f(0) + n + (n - 1) + ... + 1
= 1 + (1 + n) * n / 2
(2)若每次使用两条直线分割,即此时的n相当于原来的2n,可得:
递推公式2:

f(0) = 1
f(1) = 4
f(2) = 11
...
f(n) = f(n - 1) + 2 * n - 1 + 2 * n = f(n - 1) + 4 * n - 1

通项公式推导2_1:

f(n)
= f(n - 1) + (4 * n - 1)
= f(n - 2) + 4 * (n - 1) - 1 + (4 * n - 1)
= ...
= f(0) + (4 * 1 - 1) + (4 * 2 - 1) + ... + (4 * n - 1)
= 1 + 4 * (1 + 2 + .. + n) - n
= 1 + 4 * (1 + n) * n / 2 - n
= 1 + 2 * n * n + n

上面的推导公式比较复杂,其实也可以直接将通项公式推导1中推导结果的n用2n替代,这样就容易理解多

了:
通项公式推导2_2:

f(n)
= 1 + (1 + (2 * n)) * (2 * n) / 2
= 1 + 2 * n * n + n
(3)若是普通直线,相交处所分割的平面为4份,而折线为两份,即每次分割比上面所考虑的情况少2份

,那么只要在上述情况的每次分割时减去2就能得到本题的结果了。

递推公式3:

f(n)
= f(n - 1) + 4 * n - 1 - 2
= f(n - 1) + 4 * n - 3
通项公式:

f(n)
= 1 + 2 * n * n + n - 2 * n
= 1 + 2 * n * n - n
对于(3)这种类型,还有另外一种很好的解释(分享下!!):
分割平面的个数=交点个数+顶点个数+1
令f(n-1)为前n-1条折线分割的平面数,当添加第n条折线时。
因为每一条边与前n-1条折线的两条边都相交,故增加的交点数为2*2*(n-1),顶点增加1,故
f(n)=f(n-1)+4(n-1)+1
f(n-1)=f(n-2)+4(n-2)+1
....
f(2)=f(1)+4*1+1
f(1)=2
f(n)-2=4((n-1)+(n-2)+...+1)+(n-1)=4*((1+n-1)*(n-1)/2)+n-1=2(n*n-n)+n-1
f(n)=2n^2-n+1

可以得出公式f(n)=2n^2-n+1

总结:

直线:
最多可分为(1/2)*n*(n+1)+1块区域
折线:
那就是可以分成(2×n^2-n+1)块区域


AC代码:
#include <stdio.h>
int main()
{
    int C,n,r;
    scanf("%d",&C);
    while(C--)
    {
        scanf("%d",&n);
        r = 2*n*n - n + 1;
        printf("%d\n",r);
    }
    return 0;
}

0 0