动态规划之仓鼠吃豆子
【题目】m * n的方格上,每一格存放一定数量的豆子,一只仓鼠从左下角一直吃到右上角,但仓鼠只能向右或向上走。那么仓鼠做多可以吃多少豆子?
【思路】因为仓鼠只能向左或者向上走,那么到达任意一点的豆子数量由两部分组成:该点本身的豆子beans(x,y),max{到达左边的豆子总数path(x-1,y), 到达下方的豆子总数path(x, y-1)}。
于是得到到达任意一点的豆子总数的公式P(x,y) = F(x,y) + max(P(x-1, y), P(x, y-1))。计算并记录每个点的豆子总数,同时为了避免重复计算,将计算的中间结果存储在path数组中。
【注意】
- 因为矩阵原点在左上角,需要对公式进行变换。P(x,y) = F(x,y) + max(P(x+1, y), P(x, y-1));
- 注意边界值,这里需要注意三点,左下角的点、左边界、下边界。
#include <stdio.h> #include <stdlib.h> int max(int a, int b) { if (a > b) return a; return b; } int main() { int m, n; int i, j; int **beans; int **path; scanf("%d %d", &m, &n); /* m * n矩阵 */ beans = (int**)malloc(sizeof(void*) * m); path = (int**)malloc(sizeof(void*) * m); for (i = 0; i < m; i++) { beans[i] = (int*)malloc(sizeof(int) * n); path[i] = (int*)malloc(sizeof(int) * n); } for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &beans[i][j]); } } printf("Beans:\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { printf("%3d ", beans[i][j]); /* 显示矩阵上豆子数 */ } printf("\n"); } for (i = m - 1; i >= 0; i--) { /* to up */ for (j = 0; j < n; j++) { /* to right */ if (i == m - 1 && j == 0) { /* 左下角 */ path[i][j] = beans[i][j]; } else if (i != m - 1 && j == 0) { /* 左边界 */ path[i][j] = beans[i][j] + path[i+1][j]; } else if (i == m - 1 && j != 0) { /* 下边界 */ path[i][j] = beans[i][j] + path[i][j-1]; } else { /* 一般情况 */ path[i][j] = beans[i][j] + max(path[i+1][j], path[i][j-1]); } } } printf("Path:\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { printf("%3d ", path[i][j]); } printf("\n"); } printf("max path:%d\n", path[0][n-1]); for (i = 0; i < m; i++) { free(beans[i]); free(path[i]); } free(path); free(beans); }