关于常见矩阵路径计算问题(iOS版本)
常见类型介绍:
- /*●问题描述:
给出一个矩阵,其中0表示通路,1表示墙壁,这样就形成了一个迷宫,要求编写算法求出其中一条路径。
●递归思路:
编写一个走迷宫函数,传入二位数组的下标,先假设该点位于最终路径上(将0置为2)再探测周围四个点是否可以走通(是否为0),如果可以走通则将该点四周能走通的点作为函数参数传入函数进入递归。若四周均不能走通(都不为0时)则将该点置回0表示该点不是最终路径上的点。
在此思路中递归进入时表示了枚举路径,当发现此条路径走到某处再不能走通时就将路径该点置回0并且递归退出(回溯)寻找下一条可走通路径。
*/
/*
0 1 1 0
0 0 0 0
0 0 0 1
1 0 0 0
*/
规则中可以上下左右方向前进,求左上角到右下角的最小步数:
核心在于递归回溯判断,下面贴出代码
int mazeChat(int maze[][5],int i,int j){
int end = 0;
maze[i][j] = 2;
//如果到终点直接置为1
if (i == END_I && j == END_J) {
end = 1;
}
//不是终点则按照右下左上判断
if (end !=1 && j+1<=END_J && maze[i][j+1] == 0) {
if (mazeChat(maze, i, j+1) == 1) {
return 1;
}
}
if (end !=1 && i+1<=END_I && maze[i+1][j] == 0) {
if (mazeChat(maze, i+1, j)==1) {
return 1;
}
}
if (end !=1 && j-1>=START_J && maze[i][j-1] == 0) {
if (mazeChat(maze, i, j-1) == 1) {
return 1;
}
}
if (end !=1 && i-1>=START_I && maze[i-1][j] == 0) {
if (mazeChat(maze, i-1, j)==1) {
return 1;
}
}
//四周都没有路
if (end !=1) {
maze[i][j] = 0;
}
return end;
}
方法调用:
if (mazeChat(maze, 0, 0) == 0) {
printf("没有通道");
return;
}else{
printf("有通道\n");
}
路径会在后面的打印中根据我们预先设定的值去判断:
附上地址:demo
2.最短路径和计算:
【问题描述】: 给出一个矩阵,从左上角开始走,只能向右或者向下,所有数字累加就是路径和,求出其中最小路径。
{1,3,5,9},
{8,1,3,4},
{5,0,6,1},
{8,8,4,0}
先说一共有多少种走法:因为只能向右或者向下,所以数学方向考虑只有向右3次向下三次即可,所以简单的C6-3 即可
//走法
int uniquePaths(int m, int n)
{
int N = n + m - 2;
int K = n - 1;
double res = 1.0;
for (int i = 1; i <= n - 1; i++)
{
res = res * (N - K + i) / i;
}
return (int)res;
}
关于这个问题:
/*
【问题描述】: 给出一个矩阵,从左上角开始走,只能向右或者向下,所有数字累加就是路径和,求出其中最小路径。
思路:只允许向右或者向下走 所以开始计算时当前s[i][j]只可能从s[i-1][j]+data[i][j]或者s[i][j-1]+data[i][j]计算得到
也就是s[i][j] = min(s[i-1][j],s[i][j-1])+ data[i][j] 即需要比较s[i-1][j],s[i][j-1])
因为第一行没有s[i-1][j]元素,只有s[i][j-1]元素。
第一列没有s[i][j-1]元素,只有s[i-1][j]元素。
需要特殊处理
*/
我们通过比较每一个位置左边和上边大小而重新对该位置的值进行求和赋值即可得到一个全新的矩阵,取矩阵最后一个值即是我们需要的路径最短之和:
重新赋值矩阵方法:
//获取行数和列数
int rows = ROWS;
int cols = COLS;
//第一列
for (int i = 1; i < rows; i++)
{
data[i][0] = data[i - 1][0] + data[i][0];
}
//第一行
for (int i = 1; i < cols; i++)
{
data[0][i] = data[0][i - 1] + data[0][i];
}
//非第一行和第一列的元素
for (int i = 1; i < rows; i++)
{
for (int j = 1; j < cols; j++)
{
if (data[i][j-1] > data[i-1][j]) {
data[i][j] = data[i - 1][j] + data[i][j];
}else{
data[i][j] = data[i][j - 1] + data[i][j];
}
}
}
//返回最短路径值
return data[rows - 1][cols - 1];
拿到最小路径和的同时也可以通过得到的新矩阵去正推或者逆推得到路径下标的走法(这种重新赋值矩阵的方法优点在于只需要遍历一次即可拿到所有想要的结果,时间和空间复杂度低。缺点在于过程中存在的零时变量太多,所以之后得到新矩阵后才去获得路径下标);
两种推算路径下标方法:
printf("最优路径坐标:\n");
int rowt = 3;
int colt = 3;
for (int i = 0; i < 7; i++) {
printf("(%d,%d)\n",rowt,colt);
if(data[rowt-1][colt] < data[rowt][colt-1]){
rowt--;
}
else{
colt--;
}
}
int g = 0;
int k = 0;
for (int j = 0; j<7; j++) {
printf("{%d,%d}",g,k);
if (data[g][k+1] < data[g+1][k]) {
k++;
}else{
g++;
}
}
附上地址:demo