HDU2050 折线分割平面(基础dp&递推)

HDU2050 折线分割平面

参考博文链接:HDU2050 折线分割平面(递推)

题目链接

HDU2050

题意

就是说,给定一个n。代表图内有多少个折线。
然后对于这些个折线,最多能划分出多少个平面?

解析

HDU2050 折线分割平面(基础dp&递推)_第1张图片
这个是最开头的状态,一个折线把平面分成了两个部分
HDU2050 折线分割平面(基础dp&递推)_第2张图片
最朴素的情况下,我们可以吧眼神聚焦到射线或者线段上,就是一条已有的直线,加入一条射线或者线段,会将原有的一个平面分割成两个。
也就是一条射线,增加一个平面。
对于第n条折线,当我们加入一条新的折线之前,现在图中存在的直线数目为:

2*(n-1)条

当我们加入了这条折线,那么最优情况下,肯定是新增的折线(两条直线)与原有的所有的直线全相交。
总共相交获得点数为:

4*(n-1)个

那么这些点会将新增加的那个折线,分割成多少个线段或者射线:

4*(n-1)+2个HDU2050 折线分割平面(基础dp&递推)_第3张图片

这样处理是因为,最顶端的部分,也就是图中绿色的部分,两条线只会产生一个新的部分。所以可以粗略的认为,一个点会产生一条新的线。
于是4*(n-1)条线,每个会产生一个平面,总共是4*(n-1)个新平面,再加上顶上绿色部分的一个,共:

4*(n-1)+1个

故对于第n个折线,其数目为:

f(n) = f(n-1)+4*(n-1)+1

于是我们可以写下O(n)的递推代码

#include
#define ll long long
using namespace std;
const int MAXN = 10000;
ll ans[MAXN];
int n;
ll solve()
{
	ans[1] = 2;
	ans[2] = 7;
	for (int i = 3; i <= n; i++)
	{
		ans[i] = ans[i-1] + 4*(i-1)+1;
	}
	return ans[n];
}
 
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		printf("%lld\n", solve());
	}
	return 0;
}

优化

很显然我们可以对其做进一步的优化。
f(n) = f(n-1) + 4*(n-1) + 1
f(n) = f(n-2) + 4*(n-2) + 4*(n-1) + 1
f(n) = f(1) + 4*(2-1) + 4*(3-1) + … + 4*(n-2) + 4*(n-1) + 1
f(n) = f(1) + 4*(1+2+3+ …+(n-2)+(n-1)) + 1
f(n) = f(1) + 4*((n-1)(n-1+1)/2) +1
f(n) = f(1) + 2
n*(n-1) +1
f(n) = 2 + 2nn - 2 +1
f(n) = 2*n^2 +1
这样的话就是O(1)了

代码

#include
#define ll long long
using namespace std;
ll n;
 
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%lld", &n);
		printf("%lld\n", 2*n*n-n+1);
	}
	return 0;
}

你可能感兴趣的:(题解,#,动态规划DP,基础dp)