程序设计实习MOOC/第十三周编程作业/D:滑雪

题目:D:滑雪
总时间限制: 1000ms 内存限制: 65536kB
描述
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

解题思路:L(i,j)表示从点(i,j)出发的最长滑行长度,一个点(i,j), 如果周围没有比它低的点,L(i,j) = 1,否则,递推公式: L(i,j) 等于(i,j)周围四个点中,比(i,j)低,且L值最大的那个点的L值,再加1。将所有点按高度从小到大排序,每个点的L值都初始化为1,从小到大遍历所有的点(用结构记录i,j和对应的高度,并按照其中的高度排序),经过一个点(i,j)时,用递推公式求L(i,j)。

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;

struct H//使用结构/类来给高度排序,同时可以记录该高度对应的i,j值 
{
    int i, j, value;
    H(int _i, int _j, int _value):i(_i),j(_j),value(_value){}
    bool operator<(const H & t)//重载大小定义 
    const//注意加上这个const,否则会报错!!! 
    {
        return value > t.value;//每次优先级最高的是高度最小的 
    }
};

int main()
{
    int r, c;
    cin >> r >> c;
    int a[r][c], l[r][c];
    priority_queue<H> queue;
    for(int i = 0; i < r; i++)
    {
        for(int j = 0; j < c; j++)
        {
            cin >> a[i][j];
            queue.push(H(i, j, a[i][j]));
            l[i][j] = 1;
        }
    }
    while(!queue.empty())
    {
        int up, down, left, right;//(i,j)上下左右四个点高度值 
        int u_l, d_l, l_l, r_l;//(i,j)上下左右四个点l值 
        H h = queue.top();//处理当前还未处理过的高度最小的点
        queue.pop();
        
        //若不想处理边界情况,可以在当时创建数组时,外面加一圈边界,即a[r+2][c+2] 
        //存储它们的高度值都是大于10000的,则对结果不会有影响,可视为平常处理
        //下面是没有加边界的处理方法,因此边界情况都要考虑到!!! 
        if(h.i == 0)
        {
            left = 10000;
            l_l = 1;
            right = a[h.i + 1][h.j];
            r_l = l[h.i + 1][h.j];//(i+1, j)的l值 
        }
        else if(h.i == r - 1)
        {
            right = 10000;
            r_l = 1; 
            left = a[h.i - 1][h.j];
            l_l = l[h.i - 1][h.j];//(i-1, j)的l值 
        }
        else
        {
            left = a[h.i - 1][h.j];
            l_l = l[h.i - 1][h.j];//(i-1, j)的l值 
            right = a[h.i + 1][h.j];
            r_l = l[h.i + 1][h.j];//(i+1, j)的l值 
        }
        
        if(h.j == 0)
        {
            up = 10000;
            u_l = 1; 
            down = a[h.i][h.j + 1];
            d_l = l[h.i][h.j + 1];//(i, j+1)的l值 
        }
        else if(h.j == c - 1)
        {
            down = 10000;
            d_l = 1;
            up = a[h.i][h.j - 1];
            u_l = l[h.i][h.j - 1];//(i, j-1)的l值 
        }
        else
        {
            up = a[h.i][h.j - 1];
            u_l = l[h.i][h.j - 1];//(i, j-1)的l值 
            down = a[h.i][h.j + 1];
            d_l = l[h.i][h.j + 1];//(i, j+1)的l值 
        }
        
        //(i,j)的上下左右四个点中高度比点(i,j)高度低的点,其l值是已知的,(而高度更高的点l值还未更新,只为1)
        //但这里只用高度更低,l值已知的点,只能用它们的l值来更新(i,j)点的l值 
        //找到里面l值最大的,再加一即l[i][j],若没有比它低的点,则l[i][j]值不变
        if(left < a[h.i][h.j])//也可写出h.value
            l[h.i][h.j] = max(l[h.i][h.j], l_l + 1);
        if(right < a[h.i][h.j])
            l[h.i][h.j] = max(l[h.i][h.j], r_l + 1);
        if(up < a[h.i][h.j])
            l[h.i][h.j] = max(l[h.i][h.j], u_l + 1);
        if(down < a[h.i][h.j])
            l[h.i][h.j] = max(l[h.i][h.j], d_l + 1);
    }
    
    int max_l = 1;
    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            max_l = max(max_l, l[i][j]);
    cout << max_l <<endl;
    
    system("pause");
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值