题目:http://poj.org/problem?id=1088
据说是一道很经典的dp入门题
我的做法是用一个二维数组储存原始数据,然后对每个点调用一个递归函数,寻找周围四个方向的最长路径,加1作为这个点的最长路径。递归的方法是,对周围的四个点,如果点在地图内且高度下降,再找这个点的四个方向上的点,于是当达到边界或是某点已经被计算过,递归结束,返回最长路径值。所以这里还用到了记忆化搜索,对于每个点,都要记录这个点的最长路径值,这样就避免重复计算,是一种用空间换时间的做法。
对地图中的每个点都要调用子函数递归计算该点可以达到的路径最大值。然后比较出一个最大的作为该地图的最长路径。
要注意地图边界条件的限制,不要把行和列弄混了。
我做完之后输出数据一直有错误,后来把三个全局变量改成局部变量之后就对了。虽然我用了局部调试看了各变量值的变化,但是竟然没有意识到值的变化又问题……纠结了两个晚上,教训啊……
附代码…… 写的不好,还希望多多指教啊
AC code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100 + 10
int r, c; //行和列
int i, j;
int map[MAX][MAX]; //储存初始数据
int high[MAX][MAX] = {0}; //记忆路径值
int dx[4] = {0, 0, 1,-1}, //枚举四个方向
dy[4] = {1,-1, 0, 0};
int inarea (int x, int y) {
return x > 0 && x <= r && y > 0 && y <= c; //判断越界
}
int root (int i, int j) {
int tx, ty; //当前位置 一定是局部变量
int k; //k一定是局部变量 如果是全局变量 递归之后k = 4 ,就会出现计算错误
int maxn = 0; //当前路径最大值
if (high[i][j] > 0) //此处路径计算过
return high[i][j];
for (k = 0; k < 4; k++) { //枚举四个方向
tx = i + dx[k]; // 当前x
ty = j + dy[k]; // 当前y
if (inarea(tx, ty) && map[tx][ty] < map[i][j]) { //当前x、y在地图内,且高度下降
high[tx][ty] = root(tx, ty);
if (root(tx, ty) > maxn)
maxn = root(tx, ty); //更新最大值
}
}
high[i][j] = maxn + 1; //加上当前点
return high[i][j];
}
int main () {
int max = 0;
scanf ("%d%d", &r, &c); //输入行、列
for (i = 1; i <= r; i++)
for (j = 1; j <= c; j++)
scanf ("%d", &map[i][j]); //输入地图
for (i = 1; i <= r; i++)
for (j = 1; j <= c; j++) //对每个点调用子函数递归计算路径
if (root(i, j) > max)
max = high[i][j]; //记录最大路径
printf ("%d\n", max);
//system ("pause");
return 0;
}
这道题还有一种做法,是用一维数组储存原始数据,然后用qsort直接按从高到低排好序。但是这种做法要用到结构体,有兴趣的同学可以尝试一下。
我好菜的…… 写的不好不要批评的太严厉啊……谢谢啦~