滑雪
问题描述
Michael 喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激。可是为了获得速
度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待
升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组
给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面
的例子中,一条可滑行的滑坡为 24-17-16-1。当然 25-24-23-…-3-2-1 更长。
事实上,这是最长的一条。
输入格式
输入的第一行表示区域的行数 R 和列数 C(1 <= R,C <= 100)。下面是 R 行,每
行有 C 个整数,代表高度 h,0<=h<=10000。
输出
输出最长区域的长度。
输入样例
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输出样例
25
定义状态co[i][j]为到坐标为(i,j)的点的最长路径
可以用动态规划的思路解决。在读入时按照点的高度排序,在接下来从低到高(从高到底亦可),有以下关系:
对于一个点而言,其路径长度无非是从四周比其低的点转移来的,不然则说明自己即为周遭最低的点。因此co[i][j] = max(co[i - 1][j], co[i + 1][j], co[i][j - 1], co[i][j + 1], 1)
另一种解法将这个问题视为“最长路”问题, 人为设定一个虚拟节点, 距离为0, 能走到任何节点,接下来即可用单源点最长路解决问题。
虚拟终点的设定也适用于最短路问题。
以下为动态规划代码。
//ski
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
struct point{
int r;
int c;
point(int _r, int _c){
r = _r;
c = _c;
}
};
//var & const
const int maxN = 101;
int r, c;
int height[maxN][maxN];
int co[maxN][maxN];
vector<point> p[10010];
int maks = 0;
int finalM = 0;
//func
void init();
void readin();
int findSmallest();
void print();
void calcCount();
bool checkbound(int _c, int _r);
bool islower(int c, int r, int c1, int r1);
int main(){
init();
readin();
calcCount();
print();
return 0;
}
void init(){
freopen("ski.in", "r", stdin);
freopen("ski.out", "w", stdout);
r = c = 0;
memset(height, -1, sizeof(height));
memset(co, -1, sizeof(co));
}
void readin(){
cin >> r >> c;
for (int i = 1; i <= r; i++){
for (int j = 1; j <= c; j++){
cin >> height[i][j];
p[height[i][j]].push_back(point(i, j));
if (height[i][j] > maks) maks = height[i][j];
}
}
}
int findSmallest(){
for (int i = 0; i <= maks; i++){
if (!p[i].empty()){
return i;
}
}
return -1;
}
bool checkbound(int _c, int _r){
return (0 <= _c && _c <= c) && (0 <= _r && _r <= r);
}
bool islower(int c, int r, int c1, int r1){
return (height[r][c] < height[r1][c1]);
}
void calcCount(){
int s = findSmallest();
for (int i = 0; i < p[s].size(); i++){
co[p[s][i].r][p[s][i].c] = 1;
}
for (int i = s; i <= maks; i++){
for (int j = 0;j < p[i].size(); j++){
int c = p[i][j].c;
int r = p[i][j].r;
co[r][c] = 1;
if (checkbound(c - 1, r) && islower(c - 1, r, c, r)) co[r][c] = max(co[r][c], co[r][c - 1] + 1);
if (checkbound(c + 1, r) && islower(c + 1, r, c, r)) co[r][c] = max(co[r][c], co[r][c + 1] + 1);
if (checkbound(c, r + 1) && islower(c, r + 1, c, r)) co[r][c] = max(co[r][c], co[r + 1][c] + 1);
if (checkbound(c, r - 1) && islower(c, r - 1, c, r)) co[r][c] = max(co[r][c], co[r - 1][c] + 1);
if (co[r][c] > finalM) finalM = co[r][c];
}
}
}
void print(){
cout << finalM << endl;
}