ACM训练 训练方式 [简单递归+记忆化搜索]

题目

题目描述

自行车选手在训练时,需要围绕着场地骑行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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值