台阶问题
分析
第一眼看到这题的时候就直接想用Dfs模拟走路的过程,可是发现n数据范围为1e5,就计算一下复杂度。接近O(2n)
无非就是tle。但是为了练习我的dfs模板,于是我就手打一遍Tle的dfs,代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll cnt=0,n,k,p=100003;
void dfs(ll num){
if(num==n) {cnt++;cnt=cnt%p;return ;}
if(num>n) return ;
for(int i=1;i<=k;i++){
dfs(num+i);
}
return;
}
int main(){
scanf("%lld%lld",&n,&k);
dfs(0);
cout<<cnt<<endl;
return 0;
}
///dfs的复杂度是2^n tle
接下来,我就想用什么来优化dfs呢?dp突然出现在我的脑海里面,分析一波dp可用性,发现符合最小子问题
于是,我就假设初始位置为j,目标位置为i,那么dp[dis]表示走到dis的时候所用的所有可能方式。我们接下来考虑
怎样从j转移到i位置呢?
从j位置走到i位置,分j=i−k,i−(k−1),i−(k−2),......,i−1这些位置走一步到达,那么我们就可以利用循环来更新dp[i]
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){/判断条件需要修改,这里只是为了说明怎么走
dp[i]=dp[i]+dp[i-j];
}
}
细心的你可以发现当i小与等于k的时候会出现错误。没错,就是这样,这里我们就可以在上面的判断条件中改一下
把j<=k改成j<=k&&i-j>=0
AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,k,p=100003,dp[maxn];
int main(){
scanf("%d%d",&n,&k);
dp[0]=dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=k&&i-j>=0;j++){
dp[i]=(dp[i]+dp[i-j])%p;
}
}
cout<<dp[n]<<endl;
return 0;
}
备注,ll数据处理比int数据慢很多,见下图