题目描述
现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。
给定一个地图map及它的长宽n和m,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。
测试样例:
[[0,1,0],[2,0,0]],2,3
返回:2
解题思路:
因为题目限制了在某个位置经理只能往两个方向走,所以就经理全程只有四种可以走的走法分别为左上、左下、右上、右下。所以一开始要判断经理和商家的方向,找到其行走的方向,若商家在经理的左下方则经理全程只能向左或者向下行走。
例如经理在黄色位置,商家在蓝色位置,橘色的为不能走的位置,空白的为可以走的路径,则经理只能往左下走。
动态规划思想:
每一个位置可以走的位置可以由其左上、左下、右上、右下相加得到,当选定一个方向之后只能由该方向的相加得到,如上面的例子只能由其上方和右边两个位置可达路径相加。
所以一开始只能由经理所在的位置往商家所在的位置斜着移动,动态的获得路径和。
经理只能往下或者往走,所以其到商家的位置等于商家所在的位置的上方位置的可达路径数+商家所在的位置的右方的可到达路径数的和,即为2。
代码
public int countPath(int[][] map, int n, int m) {
// write code here
// int solveSum = 0;
int r = 0, c = 0;
int comRow = -1, comCol = -1, businessRow = -1, businessCol = -1;
// 寻找公司和商人所在的位置
for (r = 0; r < n; r++) {
for (c = 0; c < m; c++) {
if (map[r][c] == 1) {
comRow = r + 1;// 公司所在的行,+1是方便后面进行计算
comCol = c + 1;// 公司所在的列,+1是方便后面进行计算
}
if (map[r][c] == 2) {
businessRow = r + 1;// 商人所在的行,+1是方便后面进行计算
businessCol = c + 1;// 商人所在的列,+1是方便后面进行计算
}
if (comRow != -1 && businessRow != -1)
break;
}
}
int rd = businessRow - comRow, cd = businessCol - comCol;
int solveMap[][] = new int[n + 2][m + 2];// 解决方案矩阵
for (r = 0; r < n; r++) {
for (c = 0; c < m; c++) {
if (map[r][c] != -1)
solveMap[r + 1][c + 1] = 0;
else
solveMap[r + 1][c + 1] = -1;
}
}
for (r = 0; r < n + 2; r++) {// 外围的解都等于-1不可达
solveMap[r][0] = -1;
solveMap[r][m + 1] = -1;
}
for (c = 0; c < m + 2; c++) {
solveMap[0][c] = -1;
solveMap[n + 1][c] = -1;
}
int tmp = 0;
tmp = comRow;
int rdirection = businessRow > comRow ? 1 : -1;
for (r = 0; r < Math.abs(rd); r++) {// 处理和该公司所在列的可达方案数顶多为1
tmp = tmp + rdirection;// 判断是加还是减
if (solveMap[tmp][comCol] == -1 || solveMap[tmp - rdirection][comCol] == -1)
solveMap[tmp][comCol] = -1;// 判断当前位置是否为-1,或者前一行是否为-1
else
solveMap[tmp][comCol] = 1;// 当前位置都为1
}
tmp = comCol;
int cdirection = businessCol > comCol ? 1 : -1;
for (c = 0; c < Math.abs(cd); c++) {
tmp = tmp + cdirection;// 判断是加还是减
if (solveMap[comRow][tmp] == -1 || solveMap[comRow][tmp - cdirection] == -1)
solveMap[comRow][tmp] = -1;
else
solveMap[comRow][tmp] = 1;// 当前位置的为1
}
// for(r=0; r < n+2; r++){
// for(c = 0; c < m+2; c++){
// System.out.print(solveMap[r][c]+" ");
// }
// System.out.println();
// }
// 动态规划求解
int tmpRow = comRow;
for (r = 0; r < Math.abs(rd); r++) {
int tmpCol = comCol;
tmpRow += rdirection;
for (c = 0; c < Math.abs(cd); c++) {
tmpCol += cdirection;
solveMap[tmpRow][tmpCol] = towSum(solveMap[tmpRow][tmpCol - cdirection],
solveMap[tmpRow - rdirection][tmpCol]);// 等于前一行或者同行两个的和
}
}
// for(r=0; r < n+2; r++){
// for(c = 0; c < m+2; c++){
// System.out.print(solveMap[r][c]+" ");
// }
// System.out.println();
// }
return solveMap[businessRow][businessCol];
}
/**
* 返回两个数的正数和,若两则都为负数则返回0
* @param a
* @param b
* @return
*/
int towSum(int a, int b) {
int sum = a;
if (a < 0)
sum = 0;
if (b > 0)
sum = sum + b;
return sum;
}
这个题目理解了半天,描述的不是很清楚,经理到商家只能向两个方向移动,其他方向不能移动。
该博客介绍了一个使用动态规划求解的问题,经理从某个位置出发,只能沿着两个特定方向(左下或右上)移动,目标是找到到达商家的最短路径。文章通过举例说明解题思路,解释了如何根据经理和商家的位置确定可行路径,并用代码展示了解决方案矩阵的初始化和填充过程。
347

被折叠的 条评论
为什么被折叠?



