由简单的开始学习DP,参考他人的DP题目列表,于是找最简单的题目做。照我这个年纪,做这种题目会不会很丢人,暂且不管之。
递归的定义的话,从“区域最长的”高度 H 点往下滑,滑到上下左右的某一个 H-1 点处,则 H-1 位置处也是上下左右4个点中 “区域最长的”点。
原因很简单:如果 H-1 处不是“区域最长的”点,那么可以从上下左右4个点中另外取1个“区域最长的”点作为滑下的点,加上 H 点区域会变得更长。与之前 H 点上“区域最长的”点矛盾。
则递归表达式大致是:
f(h) = f(h-1)+1 ; if h!=1
f(h) = 1; if h==1
递归后会造成无数次的重复,效率太低。很典型的DP问题,自底向上则会使效率快很多。
大致伪代码:
for H 点 in 从小到大排序的高度
{
for M 点 in 矩阵中所有的点
{
for N 点 in M点的上下左右的4个点
{
if (N点的高度>M点的高度 && N点的最长区域<M点最长区域+1)
N点的最长区域 = M点最长区域+1;
}
}
}
遍历矩阵中所有的点,找出区域最长的点,输出
我的源代码如下:
1: #include <iostream>
2: using namespace std;
3: const int ITEM_SIZE = 10001;
4: const int ARR_SIZE = 100;
5:
6: struct ItemNode
7: {
8: int hight;
9: int length;
10: };
11: ItemNode item[ARR_SIZE][ARR_SIZE];
12: void initItem()
13: {
14: for (int i=0; i<ARR_SIZE; i++)
15: {
16: for (int j=0; j<ARR_SIZE; j++)
17: {
18: item[i][j].hight = 0;
19: item[i][j].length = 0;
20: }
21: }
22: }
23:
24: int main()
25: {
26: initItem();
27: int row=0, column=0;
28: int maxHight=0, minHight=ITEM_SIZE-1;
29: cin >> row >> column;
30: if (row<=0 || column<=0 || row>ARR_SIZE || column>ARR_SIZE)
31: return -1;
32:
33: for (int i=0; i<row; i++)
34: {
35: for (int j=0; j<column; j++)
36: {
37: cin >> item[i][j].hight;
38: maxHight = maxHight<item[i][j].hight ? item[i][j].hight : maxHight;
39: minHight = minHight>item[i][j].hight ? item[i][j].hight : minHight;
40: }
41: }
42:
43: for (int hight=minHight; hight<=maxHight; hight++)
44: {
45: for (int i=0; i<ARR_SIZE; i++)
46: {
47: for (int j=0; j<ARR_SIZE; j++)
48: {
49: if (item[i][j].hight==hight)
50: {
51: if (i-1>=0 && item[i-1][j].hight>item[i][j].hight && item[i-1][j].length<item[i][j].length+1)
52: item[i-1][j].length = item[i][j].length+1;
53: if (i+1<row && item[i+1][j].hight>item[i][j].hight && item[i+1][j].length<item[i][j].length+1)
54: item[i+1][j].length = item[i][j].length+1;
55: if (j-1>=0 && item[i][j-1].hight>item[i][j].hight && item[i][j-1].length<item[i][j].length+1)
56: item[i][j-1].length = item[i][j].length+1;
57: if (j+1<column && item[i][j+1].hight>item[i][j].hight && item[i][j+1].length<item[i][j].length+1)
58: item[i][j+1].length = item[i][j].length+1;
59: }
60: }
61: }
62: }
63: int res = 0;
64: for (int i=0; i<ARR_SIZE; i++)
65: {
66: for (int j=0; j<ARR_SIZE; j++)
67: {
68: res = res<item[i][j].length ? item[i][j].length:res;
69: }
70: }
71: cout << res+1 << endl;
72: return 0;
73: }
关于测试数据,除开题目给的一组,这里另给一组,来源
4 4 1 2 2 1 1 4 4 1 1 3 3 1 1 2 2 1
输出结果很显然,为4.