滑雪
来源:互联网 发布:mac系统还原 编辑:程序博客网 时间:2024/04/29 04:08
滑雪
问题描述
Michael 喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激。可是为了获得速
度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待
升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组
给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 516 17 18 19 615 24 25 20 714 23 22 21 813 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 51 2 3 4 516 17 18 19 615 24 25 20 714 23 22 21 813 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 & constconst int maxN = 101;int r, c;int height[maxN][maxN];int co[maxN][maxN];vector<point> p[10010];int maks = 0;int finalM = 0;//funcvoid 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;}