2017美团---网格走法数目
题目描述
有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。
输入描述:
输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。
输出描述:
输出包括一行,为走法的数目。
示例1
输入
3 2
输出
10
题目链接:https://www.nowcoder.com/practice/e27b9fc9c0ec4a17a5064fb6f5ab13e4?tpId=85&tqId=29883&tPage=1&rp=1&ru=/ta/2017test&qru=/ta/2017test/question-ranking
题解:利用深搜,很蒙蔽的过了,这段代码可以说是java版的深搜模板。只能往右和往下走,不用标记数组,穷举出所有的走法情况,并计算走法总数可得最终解。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 5 public class Main { 6 7 public static void main(String[] args) throws IOException { 8 BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 9 String line = in.readLine(); 10 String[] pos = line.split(" "); 11 int x = Integer.parseInt(pos[0]); 12 int y = Integer.parseInt(pos[1]); 13 int cnt = dfs(0, 0, x, y, 0); 14 System.out.println(cnt); 15 } 16 public static int dfs(int x, int y, int end_x, int end_y, int cnt) { 17 if(x == end_x && y == end_y) { 18 cnt++; 19 return cnt; 20 } 21 int res = 0; 22 for(int i = 0; i < 2; i++) {//循环往右和往下走 23 int next_x, next_y; 24 if(i == 0) {//往下走 25 next_x = x + 1; 26 next_y = y; 27 } 28 else {//往右走 29 next_x = x; 30 next_y = y + 1; 31 } 32 if(next_x <= end_x && next_y <= end_y) {//只要不出边界,则进dfs 33 cnt = dfs(next_x, next_y, end_x, end_y, cnt); 34 } 35 } 36 return cnt; 37 } 38 }
借鉴:
法一:由裴波那挈数列引申出的dp思想,由于只能往右和往下走,所以这里有dp方程式:dp[m][n] = dp[m-1][n] + dp[m][n-1]。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int[][] dp = new int[x + 1][y + 1]; 2 for(int i = 0; i <= x; i++) {//初始化 3 dp[i][0] = 1; 4 } 5 for(int i = 0; i <= y; i++) {//初始化 6 dp[0][i] = 1; 7 } 8 for(int i = 1; i <= x; i++) { 9 for(int j = 1; j <= y; j++) {//穷举不需要判断if 10 dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 11 } 12 } 13 System.out.println(dp[x][y]);
法二:为了节省上面dp数组的空间,这里直接用递归解决,思想还是上面的dp思想,可以从两个方向入手,第一个是从最初始到最终行和列,递归返回的时候是从最终行和列返回的;第二个是从最终行和列到最初始,递归返回的时候是从最初始返回的。但是两个的递归结束条件一定要用||连接,而不要用&&连接,因为||是为了防止出界。一旦任意一个坐标走到边界处就表示该return了。
第一个:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public static int dfs(int x, int y, int end_x, int end_y, int cnt) { 2 if(x == end_x || y == end_y) { 3 cnt++; 4 return cnt; 5 } 6 else { 7 return dfs(x + 1, y, end_x, end_y, cnt) + dfs(x, y + 1, end_x, end_y, cnt); 8 } 9 }
第二个:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public static int dfs(int x, int y) { 2 if(x == 0 || y == 0) { 3 return 1; 4 } 5 else { 6 return dfs(x - 1, y) + dfs(x, y - 1); 7 } 8 }