P5999 [CEOI2016] kangaroo 蓝 题解
前言
有些题目照常 DP 不是很好做,感觉像是区间 DP,但是怎么设状态都不好转移,那么可以考虑一种维护块儿的 DP,就是这道题要用到的知识点。
背景分析
如果每次跳跃的点的编号形成一个序列的话,那么这个序列满足“波浪形”,即
那么转化问题,求
前置知识
该题这种 DP 维护的是一个个块,可以设状态
比如:
每新填一个数,这个数可以开一个新块儿,也可以根据这个数合并之前的块儿,我们具体分析。
加新块
如果加数字
合并块
如果加数字
所以方程是
这道题目
我们依旧是填数,从
考虑到
为什么?
如果
如果
那么加新块的状态转移方程为:
若
对于合并块的操作无影响。
那么对于
Code
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const LL N = 2e3 + 10;
const LL mod = 1e9 + 7;
LL n, s, t;
LL f[N][N];
int main()
{
cin >> n >> s >> t;
f[1][1] = 1;
for (LL i = 2; i <= n; i ++ )
{
for (LL j = 1; j <= i; j ++ )
{
if (i == s || i == t)
{
f[i][j] = (f[i][j] + f[i - 1][j - 1] + f[i - 1][j]) % mod;
continue;
}
f[i][j] = (f[i][j] + f[i - 1][j - 1] * (j - (i > s) - (i > t))) % mod;
f[i][j] = (f[i][j] + f[i - 1][j + 1] * j) % mod;
}
}
cout << f[n][1] << endl;
return 0;
}
尾声
自己做不会,看题解也挺蒙的,搞了一下午才明白。
完结撒花!
本文作者:LittleMoMol
本文链接:https://www.cnblogs.com/LittleMoMol-kawayi/p/solution_LuoGu_P5999.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步