拜访
拜访
题目描述
现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。
给定一个地图map及它的长宽n和m,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。
测试样例:
[[0,1,0],[2,0,0]],2,3
返回:2
牛客网题解:
链接:https://www.nowcoder.com/questionTerminal/12cbdcdf5d1e4059b6ddd420de6342b6
来源:牛客网
想说的是题目描述有点模糊,通过测试才发现,“他只能在左右中选择一个方向,在上下中选择一个方向”应该理解为:左右中只能选一个方向,若选择左只能一直向左走。上下中只能选择一个方向,若选择下只能一直向下。
解题思路:
1.首先找到1和2的位置,这里要注意一点,从1走到2与从2走到1所得的路径数相同,即以1为起点或以2为起点是等价的。所以我做的处理是,统一从行坐标小的位置走到行坐标大的位置,即向下走。
2.1和2的相对位置可以归纳如下:
(1)两者位于主对角线上
(2)两者位于副对角线上
(3)两者位置重合或处于同一行或同一列(该特殊情形可以合并到(1)(2)中)
3.接下来的问题就是分别对向左走和向右走的情形应用动态规划求解。
4.代码如下,已AC。
1 public int countPath(int[][] map, int n, int m) { 2 // 首先找出1和2所在的位置 3 int i,j; 4 int x1=0,x2 = 0,y1 = 0,y2 = 0; 5 for (i = 0; i < n; i++) { 6 for (j = 0; j < m; j++) { 7 if(map[i][j]==1){ 8 x1 = i;y1=j; 9 }else if(map[i][j]==2){ 10 x2=i;y2=j; 11 } 12 } 13 } 14 if(x1==x2&&y1==y2){// 两点重合 15 return 1; 16 } 17 if(x1>x2){// x1,y1用于保存行下标的较小者 18 x1 = x1^x2^(x2=x1); 19 y1 = y1^y2^(y2=y1); 20 } 21 int dp[][] = new int[n][m]; 22 if(y1<y2){// 两点处在主对角线上 23 dp[x1][y1] = 1; 24 for (i = x1+1; i<=x2; i++) { 25 dp[i][y1] = map[i][y1]==-1?0:dp[i-1][y1]; 26 } 27 for (j = y1+1; j <=y2; j++) { 28 dp[x1][j] = map[x1][j]==-1?0:dp[x1][j-1]; 29 } 30 for (i = x1+1; i <= x2; i++) { 31 for (j = y1+1; j <=y2; j++) { 32 dp[i][j] = map[i][j]==-1?0:dp[i-1][j]+dp[i][j-1]; 33 } 34 } 35 }else{// 两者处在副对角线上 36 dp[x1][y1] = 1; 37 for (i = x1+1; i<=x2; i++) { 38 dp[i][y1] = map[i][y1]==-1?0:dp[i-1][y1]; 39 } 40 for (j = y1-1; j >=y2; j--) { 41 dp[x1][j] = map[x1][j]==-1?0:dp[x1][j+1]; 42 } 43 for (i = x1+1; i <= x2; i++) { 44 for (j = y1-1; j >=y2; j--) { 45 dp[i][j] = map[i][j]==-1?0:dp[i-1][j]+dp[i][j+1]; 46 } 47 } 48 } 49 return dp[x2][y2]; 50 }