hdu2050折线分割平面&hdu1290献给杭电五十周年校庆的礼物

hdu2050

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

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

 

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

 

Sample Input
  
  
2 1 2
 

Sample Output
  
  
2 7
 

hdu 1290:

Problem Description
或许你曾经牢骚满腹
或许你依然心怀忧伤
或许你近在咫尺
或许你我天各一方

对于每一个学子
母校 
永远航行在
生命的海洋

今年是我们杭电建校五十周年,这是一个值得祝福的日子。我们该送给母校一个怎样的礼物呢?对于目前的大家来说,最好的礼物当然是省赛中的好成绩,我不能参赛,就送给学校一个DOOM III球形大蛋糕吧,这可是名牌,估计要花掉我半年的银子呢。

想象着正式校庆那一天,校长亲自操刀,把这个大蛋糕分给各地赶来祝贺的校友们,大家一定很高兴,呵呵,流口水了吧...

等一等,吃蛋糕之前先考大家一个问题:如果校长大人在蛋糕上切了N刀(校长刀法极好,每一刀都是一个绝对的平面),最多可以把这个球形蛋糕切成几块呢?

做不出这个题目,没有蛋糕吃的!
为-了-母-校-,为-了-蛋-糕-(不是为了DGMM,枫之羽最会浮想联翩...),加-油-!
 

Input
输入数据包含多个测试实例,每个实例占一行,每行包含一个整数n(1<=n<=1000),表示切的刀数。
 

Output
对于每组输入数据,请输出对应的蛋糕块数,每个测试实例输出一行。
 

Sample Input
  
  
1 2 3
 

Sample Output
  
  
2 4 8
 
之所以把这两道题放在一块儿,是因为这两道题都属于一种类型,我称之为:分割问题。对于这种问题,一般都是自己多列举几个数据,然后总结规律。总结出可以解决的数学公式或者是递推公式。因此,这种题往往代码几行就完事,但是总结规律的过程却是很让人头疼。
一、对于分割问题,我们先从直线分割平面开始说起:一条直线能最多能把一个平面分成2份儿;两条直线最多能把直线分成4份儿……那么n个直线能把一个平面最多分成多少份儿呢?我们设这个函数为f(n),即:n条直线能够把平面最多分成f(n)份儿。通过这个函数定义,我们知道若n-1条直线的话,能够将平面最多分成f(n-1)份儿。第n条直线加进来的时候,如何能使这个平面分出最多的份儿呢?答案是:让这第n条直线与另外n-1条直线都相交,且没有公共交点。这样一来这条直线与另外n-1条直线就有n-1个交点。这n-1个交点将这第n条直线分成了两条射线和n-2条线段,每个射线和线段都将其所在的区域分成了两个区域,所以多出了2 + (n - 2) = n个区域。所以递推公式为:f(n) = f(n-1) + n。
如果非要总结出一个具体的数学公式的话:
f(n) = f(n-1) + n = f(n-2) + (n-1)  + n = f(n-3) +  (n-2) + (n-1) + n = …… = f(1) + (2 + 3 + …… +n) = 2 + (2 + 3 + 4 + …… + n) = (1+n)*n/2 + 1

二、然后我们加大点儿难度,讨论折线分割平面的问题。也就是hdu2050所说的内容。
方法同上一个问题一样,我们先设这个函数为f(n),即:n条折线能够把平面最多分成f(n)份儿。通过这个函数定义,我们知道若n-1条折线的话,能够将平面最多分成f(n-1)份儿。在n-1条折线的基础上如何将现有的平面分成最多的份儿呢?让这第n条折线的两边与另外n-1条折线的两边(一共有2*(n-1)条)都相交。这样一共就能够增加4*(n-1)个区域,再加上这条折线“尖”部的部分,这个“尖”能使其所在的区域增加一个区域。所以递推公式就是:f(n) = f(n-1) + 4*(n-1) + 1。
总结数学公式:
f(n) = f(n-1) + 4*(n-1) + 1 = f(n-2) + 4(n-2) +2 = f(n-3) + 4*(n-3) + 4*(n-2) + 4*(n-1) + 3 = ……= f(1) + 4*[1+2+3+……+(n-1)] + (n-1) = 2*n^2 - n + 1.
所以hdu2050的代码就是(递推的方法):
#include<iostream>
#include<cstdio>
using namespace std;
long long f[10005];
int main()
{
	int n,m;
	f[1]=2;
	for(int i=2;i<=10000;i++)
        {
		f[i]=f[i-1]+(2*(i-1)-1)*2+3;
	}
	scanf("%d",&n);
	while(n--)
        {
		scanf("%d",&m);
		printf("%lld\n",f[m]);
	}
	return 0;
}
套总结出来的数学公式也可以。
#include<iostream>
using namespace std;
long long fun(int m)
{
    return 2*m*m - m + 1;
}
int main()
{
	int n,m;
	cin>>n;
	while(n--)
        {
		cin>>m;
		cout<<fun(m)<<endl;
	}
	return 0;
}
三、封闭曲线分平面问题
设这个函数为f(n),即:n条封闭曲线能够把平面最多分成f(n)份儿。通过这个函数定义,我们知道若n-1条封闭曲线的话,能够将平面最多分成f(n-1)份儿。在n-1条曲线的基础上增加一条封闭曲线,当这条封闭曲线与另外n-1条封闭曲线都相交,切没有公共交点的时候能够分出最多的区域,此时能使现有区域增加2*(n-1)个区域。所以递推公式就是:f(n) = f(n-1) + 2*(n-1)
相应的数学公式就是:
f(n) = f(n-1) + 2*(n-1) = f(n-2) + 2*(n-2) + 2*(n-1) = f(n-3) + 2(n-3) + 2(n-2) + 2(n-1) = …… = f(1) + 2*[1+2+3+……+(n-1)] = 2 + 2*[1+2+3+……+(n-1)]  = n*n - n + 2

四.平面分割空间问题,也就是hdu1290的内容。
设这个函数为f(n),即:n个平面能够把空间最多分成f(n)份儿。通过这个函数定义,我们知道若n-1个平面的话,能够将空间最多分成f(n-1)份儿。当第n个平面介入的时候,只有让这个平面和另外几个平面都相交,且没有共同的交线才能分出最多的区域。那么此时多出了多少区域。我们设n条直线最多能够将平面分成g(n)份(也就是第一个问题里所讲的东西)。那么请大家想象一下,第n个平面切下去的话,显然多出了g(n-1)块区域,所以递推公式就是:f(n) = f(n-1) + g(n-1),其中:g(n) = (1+n)*n/2 + 1。
总结数学公式的话:
f(n) = f(n-1) + 1/2*(n-1)*n + 1 = f(n-2) + 1/2*[(n-2)(n-1) + (n-1)*n] + 2 = …… = f(2) + 1/2*[1*2 + 2*3 + 3*4 + ……+ (n-1)*n] + (n-2) 
其中:
1*2 + 2*3 + 3*4 +…… + n*(n+1) = 1*(1+1)  + 2*(2+1) + 3*(3+1) + ……+ n*(n+1) = 1^2 + 1 + 2^2 + 1 + 3^2 +3 + ……+ n^2 + n
 = (1+2+3+……+n) + (1^2 + 2^2 + 3^2 + n^2) 这当中前面部分为等差数列结果为n*(n+1)/2,后半部分的结果为n*(n+1)*(2*n+1)/6  (暂时先当结论记住)
带入到原来的式子,得:f(n) = (n^3 + 5*n)/6 + 1。

所以hdu1290的代码为:
#include<iostream>
using namespace std;

int Fun(int n)
{
    return  (n*n*n + 5*n)/6 + 1;
}

int main()
{
    int n;
    while(cin>>n)
    {
        cout<<Fun(n)<<endl;
    }
    return 0;
}

也可以用递推公式:

#include<iostream>
const int MAX = 1009;
using namespace std;

int f[MAX];
int g(int n) //直线分割平面公式
{
    return (1+n)*n/2 + 1;
}

int main()
{
    f[1] = 2;
    for(int i=2;i<MAX;i++)
    {
        f[i] = f[i-1] + g(i-1);
    }

    int n;
    while(cin>>n)
    {
        cout<<f[n]<<endl;
    }
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值