题目
题目描述
自行车选手在训练时,需要围绕着场地骑行N圈。给了使得训练有效,可以一次把N全部骑完,
也可以分成若干次完成,但每次都比上一次骑的圈数要多,那么完成一次训练即骑完N圈,有多种训练方式
样例输入
6
样例输出
4
题目分析
例如,当 N = 6 时,有以下四种训练方案:
6
1 2 3
1 5
2 4
细细想来,这就是一个简单的递归,每次传递的参数是上一个已选值(这次选的不能比这个值小了)和当前剩余可用总量
若是不使用记忆化搜索,数据到100往上就比较吃力了,因此显然需要使用记忆化搜索。
整体代码
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 500
using namespace std;
long long m[maxn][maxn];
bool vis[maxn][maxn];
int dd(int i, int n) {
if (vis[i][n])
return m[i][n];
vis[i][n] = true;
if (n == 0)
return m[i][n] = 1;
else if (i >= n)
return m[i][n] = 0;
else {
for (int j = i + 1; j <= n; ++j) {
m[i][n] += dd(j, n - j);
}
return m[i][n];
}
}
int main() {
int n;
while (cin >> n) {
memset(m, 0, sizeof(m));
memset(vis, false, sizeof(vis));
for (int i = 1; i <= n; ++i) {
dd(i, n - i);
}
for (int i = 1; i <= n; ++i)
m[0][n] += m[i][n-i];
cout << m[0][n] << endl;
}
}