#include<stdlib.h>
#include<stdio.h>
#include <time.h>
const int M = 8; // 萝卜地行数
const int N = 10; // 萝卜地列数
int v[M][N], c[M][N]; // 萝卜数矩阵,最优萝卜数矩阵
// 计算最优萝卜矩阵的函数,通过动态规划思想
int dituiluobo(int m, int n) {
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 && j == 0) {
c[0][0] = v[0][0]; // 入口处的最优萝卜数就是本身的萝卜数
} else if (i == 0 && j!= 0) {
c[0][j] = c[0][j - 1] + v[0][j]; // 最上面一行,只能从左边位置过来,累加萝卜数
} else if (i!= 0 && j == 0) {
c[i][0] = c[i - 1][0] + v[i][0]; // 最左侧一列,只能从上边位置过来,累加萝卜数
} else {
// 其他部分,选择从左边或者上边过来能获取更多萝卜的路径,加上当前位置萝卜数
c[i][j] = (c[i - 1][j] > c[i][j - 1]? c[i - 1][j] : c[i][j - 1]) + v[i][j];
}
}
}
return c[m][n]; // 返回最优萝卜矩阵右下角的值
}
// 反向寻找最优萝卜矩阵中最优解的来源,标记路径
void xunlu(int m, int n) {
int i = m, j = n;
int path[M + N][2]; // 用于存储路径坐标,最多可能走过M+N个位置
int index = 0;
while (i > 0 || j > 0) {
path[index][0] = i;
path[index][1] = j;
if (i == 0) {
j--; // 如果在第一行,只能从左往右走
} else if (j == 0) {
i--; // 如果在第一列,只能从上往下走
} else {
// 比较上边和左边位置的最优值,选择来源路径
if (c[i - 1][j] > c[i][j - 1]) {
i--;
} else {
j--;
}
}
index++;
}
path[index][0] = 0;
path[index][1] = 0; // 起点坐标
// 倒序输出路径坐标,展示走过的路径
printf("最优路径如下(坐标从右下角开始反向追溯到左上角):\n");
for (int k = index; k >= 0; k--) {
printf("(%d, %d) ", path[k][0], path[k][1]);
}
printf("\n");
}
int main() {
int i, j, count;
printf("一片萝卜地如下:\n");
srand((unsigned int)time(NULL)); // 初始化随机数种子
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
v[i][j] = rand() % 10;
c[i][j] = 0;
printf("%d ", v[i][j]);
}
printf("\n");
}
count = dituiluobo(M - 1, N - 1);
printf("递推小萝卜结果为%d\n", count);
printf("最优萝卜矩阵如下:\n");
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
printf("%d ", c[i][j]);
}
printf("\n");
}
xunlu(M - 1, N - 1);
return 0;
}
运行结果: