动态规划,dp,台阶问题(洛谷P1192)

                                  码农的生活:朴实无华,且枯燥。  


 我的题解:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MOD=100003;
int main()
{
    int n,k;
    cin>>n>>k;
    int arr[100005];
    memset(arr,0,sizeof(arr));
    arr[1]=1;
    for(int i=2;i<=k;i++)
    {
        for(int j=1;j<i;j++)
        {
            arr[i]+=arr[i-j];
            if(arr[i]>MOD) arr[i]%=MOD;
        }
        arr[i]+=1;
        if(arr[i]>MOD) arr[i]%=MOD;
    }
    for(int i=k+1;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            arr[i]+=arr[i-j];
            if(arr[i]>MOD) arr[i]%=MOD;
        }

    }
    cout<<arr[n]<<endl;
    return 0;
}

转的题解:

深搜超时,于是想到DP...

虽说是递推,但是从思想上来说我更倾向于动态规划的理解方式,因为我就是这么理解的。

定义状态f[i]:走i步台阶的方案总数;

递推公式:f[i]=sigma( j← 1 to min(i,k)) f[i-j]; j的意义是第一步先迈j个阶梯,j<=k是题意要求,j<=i因为j>i没有意义,所以j<=min(i,k);

分析状态转移公式,可以发现对于i来说,在不考虑方案对称性的前提下(也就是题目的要求,先迈一步再迈十步与先迈十步再迈一步是两个不同的方案),对于不同的j方案在一开始就不同了,所以在求和计算f[i']时因为每次i不存在重复计算的问题。

目标状态f[n],起点状态是f[1],显然f[1]=1;

初始化f[0]=1则是在后面递推的时候写着方便,f[0]的意义在于,由于我们枚举了j=min(i,k),即可能存在i==j的情况,具体意义为一步迈到终点(条件为i<=k),这一步是合法方案,所以令f[0]=1让计算一般化;

代码很短:

#include<iostream>
using namespace std;
int n,k;
int main(){
    cin>>n>>k;
    int f[n+1];
    for(int i=2;i<=n;i++) f[i]=0;
    f[1]=f[0]=1;
    for(int i=2;i<=n;i++){
        for(int j=min(i,k);j>=1;j--){
            f[i]+=f[i-j];
            if(f[i]>=100003) f[i]%=100003;        //注意取模!!!卡了我一次
        }
    }
    cout<<f[n];
    return 0;
}
发布了77 篇原创文章 · 获赞 11 · 访问量 4990

猜你喜欢

转载自blog.csdn.net/qq_43346054/article/details/103434837