题解 | #拜访#
拜访
https://www.nowcoder.com/practice/491828fc7d93459db450b344c2aaaeef
什么是动态规划
动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。
动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。
如何使用动态规划的思想解决此题
1.定义一个二维的dp数组,其中的元素与地图上的一 一对应,表示从我的地方(xMe,yMe)到该位置(i,j)的有几条最短路径
dp[i][j] :表示从(xMe,yMe)出发,到(i, j) 有dp[i][j]条不同的路径,程序最后返回dp[xDes][yDes]即可((xDes,yDes)是专家的位置)。
2.dp[i][j]的值如何得到呢?
由dp[i][j]的上一个可能的状态(有 dp[i - xDir][j] 和dp[i][j - yDir])得到。这里的xDir和yDir表示运动方向,见程序31、32行。
即dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。
但这里需要注意一点,因为有了障碍,(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0)。
3.确定了dp的获得方式和之前的状态有关之后,我们需要给dp一个初始的值,这样才能得到后面的值
初始的值选用边界是最好计算的,因为在最短路径中,能到达边界的方法只有一种。但是考虑到边界中可能出现障碍物,所以在边界中障碍物对应的dp值置零,其余置一。
4.确定遍历顺序,本题中从x开始遍历和从y开始遍历都可以,我选择从x开始遍历。
5.输出结果dp[xDes][yDes]
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param CityMap int整型二维数组
* @param CityMapRowLen int CityMap数组行数
* @param CityMapColLen int* CityMap数组列数
* @param n int整型
* @param m int整型
* @return int整型
*/
int countPath(int** CityMap, int CityMapRowLen, int* CityMapColLen, int n, int m ) {
// write code here
int i,j;//定义工具人
int xDes,yDes,xMe,yMe;//定义客户的位置(xDes、有yDes)和我的位置(xMe、yMe)
int **dp = malloc(sizeof(int *) * n);
for(i = 0; i < n; i++){
dp[i] = malloc(sizeof(int) * m);
for(j = 0; j < m; j++){
if(CityMap[i][j] == 1){
xMe = i;
yMe = j;
}
if(CityMap[i][j] == 2){
xDes = i;
yDes = j;
}
}
}
int xDir = xMe > xDes ? -1 : 1; //定义x方向
int yDir = yMe > yDes ? -1 : 1; //定义y方向
dp[xMe][yMe] = 1;
for(i = xMe + xDir; i != xDes + xDir; i += xDir){
if(CityMap[i][yMe] == -1){
dp[i][yMe] = 0;
}else{
dp[i][yMe] = 1;
}
}
for(i = yMe + yDir; i != yDes + yDir; i += yDir){
if(CityMap[xMe][i] == -1){
dp[xMe][i] = 0;
}else{
dp[xMe][i] = 1;
}
}
for(i = xMe + xDir; i != xDes + xDir; i += xDir){
for(j = yMe + yDir; j != yDes + yDir; j += yDir){
if(CityMap[i][j] == -1){
dp[i][j] = 0;
}
dp[i][j] = dp[i - xDir][j] + dp[i][j - yDir];
}
}
return dp[xDes][yDes];
}
#C#
查看14道真题和解析