输入:输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
输出:输出最长区域的长度。
解题思路:“我为人人”式递推
Len(i,j)表示从点(i,j)出发的最长滑行长度。
一个点(i,j), 如果周围没有比它低的点,Len(i,j) = 1。每个点的Len 值都初始化为1
将所有点按高度从小到大排序。
从小到大遍历所有的点。经过一个点(i,j)时,要更新他周围的,比它高的点的L值。例如:
if H(i+1,j) > H(i,j) // 上方,H代表高度
L(i+1,j) = max(L(i+1,j),L(i,j)+1)
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 100;
int len[MAX][MAX];
int high[MAX][MAX];
int R, C;
struct point{
int x,y;
int highs;
}Area[MAX];
struct Rule{
bool operator()(const point &a, const point &b){
return a.highs > b.highs;
}
};
void DP(point s[],int k)
{
for (int i = k; i >0; i--)//自小到大遍历
{
int r = Area[i].x;
int c = Area[i].y;
if ((r + 1 <= R) && high[r + 1][c] > high[r][c]) //下方
len[r + 1][c] = max(len[r + 1][c], len[r][c] + 1);
if ((r - 1 >= 0) && high[r - 1][c] > high[r][c]) //上方
len[r - 1][c] = max(len[r - 1][c], len[r][c] + 1);
if ((c + 1 <= C) && high[r][c + 1] > high[r][c]) //右方
len[r][c + 1] = max(len[r][c + 1], len[r][c] + 1);
if ((c - 1 >= 0) && high[r][c - 1] > high[r][c]) //左方
len[r][c - 1] = max(len[r][c - 1], len[r][c] + 1);
}
}
int main(){
cin >> R >> C;
for (int i = 1; i <= R; ++i){
for (int j = 1; j <= C; ++j){
Area[(i-1)*C+j].x = i;
Area[(i - 1)*C + j].y = j;
cin >> high[i][j];
Area[(i - 1)*C + j].highs = high[i][j];
len[i][j] = 1;
}
}
sort(Area+1 , Area + R*C+1, Rule());//将所有点高度从大到小排序
int i = R*C;
DP(Area,R*C);
for (int i = 1; i <= R; i++){
cout << "前" << i << "种";
for (int j = 1; j <= C; ++j){
cout << len[i][j] << " ";
}
cout<<endl;
}
int tmp = 0;
for (int i = 1; i <= R; ++i)//输出数组中的最大值;
for (int j = 1; j <= C; ++j){
if (tmp < len[i][j])
tmp = len[i][j];
}
cout << tmp;
return 0;
}