题意:在二维数组中找最长的下降序列,可以向上、下、左、右,四个方向走
思路:len[i][j] = max{上,下,左,右},还需要考虑height[i][j]与上下左右的关系。
这个方程的子问题填表方式有两种:一是,迭代方式,用一个结构体记录height[i][j]、i、j,然后对高度排序,然后从小到大填表,这样就能保证填len[i][j]时,其上下左右如果不比 height[i][j]大则一定填过了;二,用备忘录方式,直接递归处理。
我用的第二种,因为当时没想起来怎么迭代处理,就用备忘录了,后来仔细想了想递归的时候的调用关系,想出了第一种方法.
代码:
#include<cstdio>
using namespace std;
int height[100][100];
int len[100][100]; //初始化为-1
int r, c;
int get_len(int i, int j){
if(len[i][j] >= 0)
return len[i][j];
int tmp;
int max = 0;
//上
if((i-1) >= 0 && height[i-1][j] < height[i][j]){
tmp = get_len(i-1, j) + 1;
if(tmp > max)
max = tmp;
}
//下
if((i+1) < r && height[i+1][j] < height[i][j]){
tmp = get_len(i+1, j) + 1;
if(tmp > max)
max = tmp;
}
//左
if((j-1) >= 0 && height[i][j-1] < height[i][j]){
tmp = get_len(i, j-1) + 1;
if(tmp > max)
max = tmp;
}
//右
if((j+1) < c && height[i][j+1] < height[i][j]){
tmp = get_len(i, j+1) + 1;
if(tmp > max)
max = tmp;
}
return max;
}
int main(){
// freopen("in", "r", stdin);
scanf("%d %d", &r, &c);
for(int i=0; i<r; ++i)
for(int j=0; j<c; ++j){
scanf("%d", &height[i][j]);
len[i][j] = -1;
}
int max_len = 0;
for(int i=0; i<r; ++i)
for(int j=0; j<c; ++j){
len[i][j] = get_len(i, j);
if(len[i][j] > max_len)
max_len = len[i][j];
}
printf("%d", max_len + 1);
return 0;
}
我又把第一种迭代法的程序写出来了:
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 100
struct index {
int x;
int y;
};
int height[MAX][MAX];
index order[MAX * MAX]; //对高度的排序
int len[MAX][MAX];
int r, c;
//用于排序的比较对象
struct cmp {
bool operator()(index a, index b) {
return (height[a.x][a.y] < height[b.x][b.y]);
}
};
//按顺序填表
void fill() {
int i, j;
int max, tmp;
for (int k = 0; k < r * c; ++k) {
i = order[k].x;
j = order[k].y;
max = 0;
//上
if ((i - 1) >= 0 && height[i - 1][j] < height[i][j]) {
tmp = len[i - 1][j] + 1;
if (tmp > max)
max = tmp;
}
//下
if ((i + 1) < r && height[i + 1][j] < height[i][j]) {
tmp = len[i + 1][j] + 1;
if (tmp > max)
max = tmp;
}
//左
if ((j - 1) >= 0 && height[i][j - 1] < height[i][j]) {
tmp = len[i][j - 1] + 1;
if (tmp > max)
max = tmp;
}
//右
if ((j + 1) < c && height[i][j + 1] < height[i][j]) {
tmp = len[i][j + 1] + 1;
if (tmp > max)
max = tmp;
}
len[i][j] = max;
}
}
int main() {
// freopen("in", "r", stdin);
scanf("%d %d", &r, &c);
for (int i = 0; i < r; ++i)
for (int j = 0; j < c; ++j) {
scanf("%d", &height[i][j]);
int k = i * c + j;
order[k].x = i;
order[k].y = j;
}
sort(order, order + r * c, cmp());
fill();
int max_len = 0;
for (int i = 0; i < r; ++i)
for (int j = 0; j < c; ++j)
if (len[i][j] > max_len) {
max_len = len[i][j];
}
printf("%d", max_len + 1);
return 0;
}