Timus Online Judge 1017 Staircases(记忆化搜索)

这道题目在Timus上面的难度系数是165,可是当你做了之后就会发现,这道题目的难度系数大概也就七八十的样子,大概动态规划一类的问题都是这样吧,推导出了状态转移方程就没什么好说的,然而我并没有推导出状态转移方程,只是用了个记忆化搜索。

题目大意:用N个格子搭楼梯,每个阶梯之间严格递增,不允许相等的情况,至少要有两个阶梯,每个阶梯至少用一个格子,并没有对相邻阶梯的高度进行限制。问,有多少种搭建方法?

如果你是新手,或许很难去找到相应的问题模型来对这道题目进行套用,因为你可能真的像题目的描述那样,一步一步的去搭建。

但如果你以前就学过dp,并且也知道有数的划分这类型的问题,那么,稍加思考,这道题目就感觉so easy!

谈到数的划分,那就直接明了了吧,我相信,我们需要考虑的就是把一个数N划分为K(k  > 1)个不相同的数,每个数要大于0,这样思路转换一下,就可以了。

枚举一下所有的可能,然后加上记忆化搜索,就完事儿了。下面还是照例献上自己丑陋的代码。

#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
ll dp[501][501];
ll solve(int sum, int mx) {//由未知的k个不同的小于mx数来组成sum,事实上,我们并不需要知道k是多少
    if (sum == 0) return 1;
    if (dp[sum][mx] != -1) return dp[sum][mx];
    ll ans = 0;
    for (int i = min(mx - 1, sum); i >= 1; --i) {//sum - i 出现负数的情况
        ans += solve(sum - i, i);
    }
    return dp[sum][mx] = ans;
}
int main() {
    ll N;
    cin >> N;
    memset(dp, -1, sizeof dp);
    ll ans = 0;
    for (int i = N - 1; i >= 1; --i) {//i不能从N开始枚举,为了避免只有一个台阶的情况
        ans += solve(N - i, i);
    }
    cout << ans << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值