机器人到达指定位置方法数

假设有排成一行的N个位置,记为1~N,开始时机器人在M位置,机器人可以往左或者往右走,如果机器人在1位置,那么下一步机器人只能走到2位置,如果机器人在N位置,那么下一步机器人只能走到N-1位置。规定机器人只能走k步,最终能来到P位置的方法有多少种。由于方案数可能比较大,所以答案需要对1e9+7取模。

输入描述:
输出包括一行四个正整数N(2<=N<=5000)、M(1<=M<=N)、K(1<=K<=5000)、P(1<=P<=N)。

输出描述:
输出一个整数,代表最终走到P的方法数对取模后的值。

示例1
输入

5 2 3 3

输出

3

说明
1).2->1,1->2,2->3

2).2->3,3->2,2->3

3).2->3,3->4,4->3
示例2

输入

1000 1 1000 1

输出

591137401

说明
注意答案要取模

################################################################################

解题思路一:暴力递归

	public static int ways1(int N,int M,int K,int P) {
		if(N<2||K<1)return 0;
		return walk1(N,M,K,P);
	}
	public static int walk1(int N,int cur,int rest,int P) {//rest:剩余的步数  cur:当前的位置
		if(rest==0)return cur==P?1:0;
		if(cur==1) {
			return walk1(N,cur+1,rest-1,P);
		}
		if(cur==N) {
			return walk1(N,cur-1,rest-1,P);
		}
		return (walk1(N,cur-1,rest-1,P)+walk1(N,cur+1,rest-1,P))%1000000007;
	}

机器人到达指定位置方法数

暴力递归改动态规划的目的只有一个:以空间换取时间,因为暴力递归细分会出现好多重复的暴力展开,浪费了时间,暴力递归改动态规划就是将已经暴力展开的子情况的值记录下来,下次再次遇到相同的子情况就不用再次浪费时间去做暴力展开了,直接用值就行了。

解题思路二:暴力递归改动态规划 1

借助傻缓存cache(哈希表实现),记忆化搜索



	public static int ways2(int N,int M,int K,int P) {
		if(N<2||K<1)return 0;
		HashMap<String,Integer>cache=new HashMap<>();
		return walk2(N,M,K,P,cache);
	}
	public static int walk2(int N,int cur,int rest,int P,HashMap<String,Integer>cache) {//rest:剩余的步数  cur:当前的位置
		String key=String.valueOf(cur)+"_"+String.valueOf(rest);
		if(cache.containsKey(key))return cache.get(key);
		int ans=0;
		if(rest==0) {
			ans=cur==P?1:0;
			cache.put(key, ans);
			return ans;
		}
		
		if(cur==1) {
			ans=walk2(N,cur+1,rest-1,P,cache);
			cache.put(key, ans);
			return ans;
		}
		if(cur==N) {
			ans=walk2(N,cur-1,rest-1,P,cache);
			cache.put(key, ans);
			return ans;
		}
		ans=(walk2(N,cur-1,rest-1,P,cache)+walk2(N,cur+1,rest-1,P,cache))%1000000007;
		cache.put(key, ans);
		return ans;
	}
	

机器人到达指定位置方法数
解题思路三:暴力递归改动态规划 2
哈希表虽然操作都是O(1),但是常数时间还是比较大的,可以采用二维数组的方法来记录。


	public static int ways3(int N,int M,int K,int P) {
		if(N<2||K<1)return 0;
		int[][] cache=new int[N+1][K+1];
		//将数组初始化为-1,表示还没求过这个值
		for(int i=1;i<cache.length;++i) {
			for(int j=0;j<cache[0].length;++j) {
				cache[i][j]=-1;
			}
		}
		return walk3(N,M,K,P,cache);
	}
	public static int walk3(int N,int cur,int rest,int P,int[][] cache) {//rest:剩余的步数  cur:当前的位置
		if(cache[cur][rest]!=-1)return cache[cur][rest];
		int ans=0;
		if(rest==0) {
			ans= cur==P?1:0;
			cache[cur][rest]=ans;
			return ans;
		}
		if(cur==1) {
			ans=walk3(N,cur+1,rest-1,P,cache);
			cache[cur][rest]=ans;
			return ans;
		}
		if(cur==N) {
			ans=walk3(N,cur-1,rest-1,P,cache);
			cache[cur][rest]=ans;
			return ans;
		}
		ans=(walk3(N,cur-1,rest-1,P,cache)+walk3(N,cur+1,rest-1,P,cache))%1000000007;
		cache[cur][rest]=ans;
		return ans;
	}

机器人到达指定位置方法数
解题思路四:暴力递归改动态规划 3
可变的参数K和M,填下面的表
N=7,M=2,K=5,P=3

先确定初始条件,第一列的第M行为1,其他为0
任何列的第一行都只依靠其左下角的值
任何列的最后一行都只依靠其左上角的值
其他位置同时依靠其左上角和左下角的值

机器人到达指定位置方法数

结果就是[M][K]的值


	public static int waysDP(int N,int start,int K,int end) {
		if(N<2||start<1||end>N||K<1||start>N||end<1)return 0;
		int[][] dp=new int[N+1][K+1];
		dp[end][0]=1;
		for(int col=1;col<=K;++col) {
			dp[1][col]=dp[2][col-1];
			dp[N][col]=dp[N-1][col-1];
			for(int row=2;row<N;++row) {
				dp[row][col]=(dp[row-1][col-1]+dp[row+1][col-1]) % 1000000007;
			}
		}
		return dp[start][K];
	}


机器人到达指定位置方法数

上一篇:简述jpg。Gif。png-8.png-24的区别,分别使用场景


下一篇:rest参数和扩展运算符的区别