且歌且行,眉目轻盈。何妨吟啸且徐行。|

胖柚の工作室

园龄:2年1个月粉丝:2关注:15

2024-04-10 10:25阅读: 7评论: 0推荐: 0

P1464 Function

题目链接:

本题为一道极其经典的记忆化搜索模板题,务必搞懂并掌握记忆化搜索的常见书写格式。

主要思想就是用一个 dp 数组将每一个 w 函数的值存储起来,下一次检查 dp[a][b][c] 的值,如果已经算过就直接调用,可节省大量时间。

#include <cstdio>
#include <cstring>
using LL = long long;
LL dp[25][25][25];
LL w(LL a, LL b, LL c) {
if (a <= 0 || b <= 0 || c <= 0) return 1;
if (a > 20 || b > 20 || c > 20) return w(20, 20, 20);
if (dp[a][b][c] != -1) return dp[a][b][c];
if (a < b && b < c) {
return dp[a][b][c] = w(a, b, c - 1) + w(a, b - 1, c - 1) - w(a, b - 1, c);
}
return dp[a][b][c] = w(a - 1, b, c) + w(a - 1, b - 1, c) + w(a - 1, b, c - 1) - w(a - 1, b - 1, c - 1);
}
int main()
{
LL a, b, c;
memset(dp, -1, sizeof dp);//记忆数组最好初始化为-1而不是0(本题初始化为0也能AC)
while (scanf("%lld%lld%lld", &a, &b, &c) != EOF) {
if (a == -1 && b == -1 && c == -1) return 0;
printf("w(%lld, %lld, %lld) = %lld\n", a, b, c, w(a, b, c));
}
}

注意memo 数组的初始值一定不能等于要记忆化的值!例如初始值设置为 0,并且要记忆化的 dfs(i) 也等于 0,那就没法判断 0 到底表示第一次遇到这个状态,还是表示之前遇到过了,从而导致记忆化失效。一般把初始值设置为 1。本题由于状态全为正值,设置为 0 也能 AC

值得注意的一点是,若把判断语句写在函数一开始,还需先判断一下 a,b,c 是否合法。

LL w(LL a, LL b, LL c) {
if (a >= 0 && a <= 25 && b >= 0 && b <= 25 && c >= 0 && c <= 25 && dp[a][b][c] != -1) return dp[a][b][c];
if (a <= 0 || b <= 0 || c <= 0) return 1;
if (a > 20 || b > 20 || c > 20) return w(20, 20, 20);
if (a < b && b < c) {
return dp[a][b][c] = w(a, b, c - 1) + w(a, b - 1, c - 1) - w(a, b - 1, c);
}
return dp[a][b][c] = w(a - 1, b, c) + w(a - 1, b - 1, c) + w(a - 1, b, c - 1) - w(a - 1, b - 1, c - 1);
}

本文作者:pangyou3s

本文链接:https://www.cnblogs.com/pangyou3s/p/18125490

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   胖柚の工作室  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起