[蓝桥杯][算法提高VIP]数的划分(记忆化搜索)

题目描述
一个正整数可以划分为多个正整数的和,比如n=3时:
3;1+2;1+1+1;
共有三种划分方法。
给出一个正整数,问有多少种划分方法。

数据规模和约定
n< =100

输入
一个正整数n
输出
一个正整数,表示划分方案数
样例输入
3
样例输出
3
思路:这是算法书的一道基础分治题目,但是这个题单纯用分治应该会TLE。因为会重复计算很多次,因此我们采用记忆化搜索,DP应该也可以。判断条件如下:
dp[x][y]代表的是当前数为x,分裂的最大数值为y的情况数。
①x==0,不可能存在这种情况,返回0.
②如果当前情况已经经历过,就直接返回结果。
③如果当前数小于分裂的最大数,那么就按照当前数作为最大分裂数。
④最大分裂数为1的时候,只有一种情况。例如6=1+1+1+1+1+1.
⑤当前数=最大分裂数的时候,返回dfs(x,y-1)+1,+1的意思是6=6这种情况,剩下的情况就是最大分裂数为5的情况了。
⑥其余的情况就是dfs(x,y-1)+dfs(x-y,y)。当前数为x,但是最大分裂数为y-1.加上当前数为x-y,最大分裂数仍为y的情况和。
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=1e2+10;
ll dp[maxx][maxx];
int n;

inline ll dfs(int x,int y)
{
	if(x==0) return 0;
	if(dp[x][y]!=-1) return dp[x][y];
	if(x<y) return dfs(x,x);
	if(y==1) return dp[x][y]=1ll;
	if(x==y) return dp[x][y]=dfs(x,y-1)+1ll;
	return dp[x][y]=dfs(x,y-1)+dfs(x-y,y);
}
int main()
{
	scanf("%d",&n);
	memset(dp,-1,sizeof(dp));
	cout<<dfs(n,n)<<endl;
	return 0;
}

努力加油a啊,(o)/~

发布了596 篇原创文章 · 获赞 47 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/105041837