踩方格(动态规划,两种递推)
Posted zyacmer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了踩方格(动态规划,两种递推)相关的知识,希望对你有一定的参考价值。
//本题给了两种递推的写法 /* 两种方法的思路总结: 都是用步数i作为迭代量 然后考虑每一步和前一步的关系 第一种方法是找出三向点和二向点的关系 第二种方法是找出当前点是由三个方向过来的,这三个方向分别又是由...过来的 再找出递推关系,再推导化简,成功优化为一元状态转移方程 */ ///ps.希望一年后我也能有这么强大的acm能力 //特别感谢蔡军帅的这篇博文让我学会这题 //他的博客:https://blog.csdn.net/qq_40875849/article/details/83053045 #include<bits/stdc++.h> #define ll long long using namespace std; /* 每一个三向的点下一步会生成一个三向的点和两个双向的点 //@3 => @3 [email protected] [email protected] 每一个双向的点下一步会生成一个三向的点和一个双向的点 //@2 => @3 [email protected] 这个可以画个图理解模拟一下 */ int a3[25];//关于三向点的数组 int a2[25];//关于二向点的数组 int main() { /* 刚刚那个规律是一直成立的,只要按着规律一直递推到 第n步有多少个三向方案和多少个双向方案就好了 */ int n; cin>>n; a2[1]=0; a3[1]=1; for(int i=2;i<=n;i++) { /* 第i步:@3 => 第i+1步:@3 [email protected] [email protected] 第i步:@2 => 第i+1步:@3 [email protected] 联立两个式子 假如现在走到第i步,现在场上有a个@3和b个@2 那么i+1步时会有a*2+b*1个@2 会有a*1+b*1个@3 */ a2[i]=2*a3[i-1]+a2[i-1]; a3[i]=a3[i-1]+a2[i-1]; } cout<<a3[n]*3+a2[n]*2<<endl; //第n步时,有a3[n]个@3和a2[n]个@2 //@3代表有三种走法,@2代表有两种走法 //直接输出3*a3[n]+2*a2[n]就好了 return 0; } //本题另一种写法 //感谢konjac的博文让我学会这题 //他的博客:https://www.cnblogs.com/konjak/p/5936888.html #include<bits/stdc++.h> using namespace std; int f[25]; int main() { /* 另一种方法是用一元数组递推,虽然说比前一种方法效率更高,但更难掌握 因为状态转移方程不能一眼看出,要靠推出来 附上konjac的推导过程(这里为转载复制!!!) 状态转移方程推导如下—— 设l[i],r[i],u[i]分别为第 i 步向西、东、北的方案数,f[i]为总方案数。 l[i]=l[i-1]+u[i-1], r[i]=r[i-1]+u[i-1], u[i]=l[i-1]+r[i-1]+u[i-1]//这行很重要,对于下面推导 //每个方向的来源都清除,左边是从左边和下面来 //右边是右边和下面来 //上边可以是左右两边来的也可以是下边来的1 f[i]=l[i]+r[i]+u[i]//f[i]由三个方向组成 =2*l[i-1]+2*r[i-1]+3*u[i-1] //把l[i],r[i],u[i]都替换掉 =2*f[i-1]+u[i-1] //然后还剩一个u[i-1]没替换 =2*f[i-1]+f[i-2] //u[i-1]=l[i-2]+r[i-2]+u[i-2]=f[i-2] 于是代码就非常简单了 */ int n; scanf("%d",&n); f[1]=3, f[2]=7; for (int i=3;i<=n;i++) f[i]=2*f[i-1]+f[i-2]; printf("%d ",f[n]); return 0; }
以上是关于踩方格(动态规划,两种递推)的主要内容,如果未能解决你的问题,请参考以下文章