回家有n个台阶,每次至少走一个,但是要求每步和之前两步走的台阶数目不能一样,请问有多少种不同的解法,答案对10^9+7取模。
输入两个整数n,m,n表示台阶数目,m表示单步最大跨越的台阶数目。
思路:老实说这题不难,但是想全A还是有点难,全A肯定要动态规划,而且是三维的动态规划,但是我觉得面试的时候也不会考这么难,所以三维的动态规划的方法就不写了,下面写了两个方法,一个是递归的,一个是记忆化搜索(带备忘录的递归)。
1、递归
就是递归每次需要传入上一次的值last和上上次的值lastlast,然后遍历可以跳跃的值1~m,如果不是last和lastlast就可以继续递归,否则跳过,代码如下:
public static int res=0;
public static void dfs1(int index,int n,int m,int last,int lastlast){
if(index==n)
{
res++;
res=res%1000000007;
}
if(index>n)
return ;
for(int i=1;i<=m;i++){
if(i!=lastlast&&i!=last){
dfs1(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
}
}
}
2、带备忘录的递归
大家都知道,递归的低效率是由于重复计算了很多子问题,因此想到把子问题保存在哈希表里面,每次递归时直接查询,如果哈希表里面没有才继续往下算,代码如下:
public static HashMap<String,Integer> map;
public static int dfs(int index,int n,int m,int last,int lastlast){
if(index==n)
{
return 1;
}
if(index>n)
return 0;
String str=index+","+last+","+lastlast;
if(map.containsKey(str))
return map.get(str);
int lastres=0;
for(int i=1;i<=m;i++){
if(i!=lastlast&&i!=last){
lastres+=dfs(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
}
}
lastres=lastres%1000000007;
map.put(str,lastres);
return lastres;
}
最后把两个代码放在一起,方便大家比较:
public static int res=0;
public static HashMap<String,Integer> map;
public static int dfs(int index,int n,int m,int last,int lastlast){
if(index==n)
{
return 1;
}
if(index>n)
return 0;
String str=index+","+last+","+lastlast;
if(map.containsKey(str))
return map.get(str);
int lastres=0;
for(int i=1;i<=m;i++){
if(i!=lastlast&&i!=last){
lastres+=dfs(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
}
}
lastres=lastres%1000000007;
map.put(str,lastres);
return lastres;
}
public static void dfs1(int index,int n,int m,int last,int lastlast){
if(index==n)
{
res++;
res=res%1000000007;
}
if(index>n)
return ;
for(int i=1;i<=m;i++){
if(i!=lastlast&&i!=last){
dfs1(index+i,n,m,i,last);//在里面进行修改,这一步的值在下一步就是last,last在下一步就是lastlast
}
}
}
public static void print(List<List<Integer>> tmp){
for(List<Integer> a:tmp){
for(Integer a1:a)
System.out.print(a1+" ");
System.out.println();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
//int n=70;
//int m=4;
int n=sc.nextInt();
int m=sc.nextInt();
map=new HashMap<>();
System.out.println("带备忘录的:");
System.out.println(dfs(0,n,m,0,0));
dfs1(0,n,m,0,0);
System.out.println("不带备忘录的");
System.out.println(res);
}