zoukankan      html  css  js  c++  java
  • 矩阵求连续递减序列个数,动态规划初级,递归,poj1088

    题目描述:

    Description

    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更长。事实上,这是最长的一条。

    Input

    输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

    Output

    输出最长区域的长度。

    Sample Input

    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
    

    Sample Output

    25


    分析:很明显这是一道动态规划的题目,一段以a开始的轨迹(a,b,c...)的长度其实等于以b开始的轨迹长度+1,那么其实这又满足了问题拆分为子问题。
    于是我敲出了一段错误的代码。。。
    如下:
    #include<iostream>
    using namespace std;
    int a[101][101]={0};
    int temp[101][101]={0};
    int m,n;
    
    int getMax(int x,int y,int z,int q){
        int arr[4]={x,y,z,q};
        int max = 0;
        for(int i=0;i<4;i++){
            if(max<arr[i]){
                max=arr[i];
            }
        }
        return max;
    }
    
    int main(){
        cin>>m>>n;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                cin>>a[i][j];
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                int x=0,y=0,z=0,p=0;
                if(i>=1&&a[i][j]>a[i-1][j]){
                    x=temp[i-1][j]+1;
                }
                if(i<=m-2&&a[i][j]>a[i+1][j]){
                    y=temp[i+1][j]+1;
                }
                if(j>=1&&a[i][j]>a[i][j-1]){
                    z=temp[i][j-1]+1;
                }
                if(j<=n-2&&a[i][j]>a[i][j+1]){
                    p=temp[i][j+1]+1;
                }
                if(x||y||z||p){
                    temp[i][j] = getMax(x,y,z,p);
                }else{
                    temp[i][j] = 1;
                }
            }
        }
        int max=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(temp[i][j]>max){
                    max=temp[i][j];
                }
            }
        }
        
        cout<<max<<endl;
        return 0;
    }

    按照上面的描述,标红代码已经体现了这个思想,可为什么还是错了呢?

    原因:我之前太过于看中这个过程,即temp[a]=temp[b]+1(a的轨迹长度=b的轨迹长度+1),其中忽视了一个重要的点,就是递减的传递性,因为我们遍历是从左至右依次遍历二维数组,那么会出现以下问题,举例说明:

    25 1
    24 2
    23 3
    假如我们开始遍历,那么25(temp[0][0])会得到1而不是25,因为我们只检查了25周围的元素有没有比25小的,小的话+1便来到了1,而非继续检查25周围的元素
    故我们需在这里使用递归直到递减无法传递(元素周围都是比它大的数)
    上代码:
    #include<iostream>
    using namespace std;
    int a[101][101]={0};
    int temp[101][101]={0};
    int m,n;
    
    int getMax(int x,int y,int z,int q){
        int arr[4]={x,y,z,q};
        int max = 0;
        for(int i=0;i<4;i++){
            if(max<arr[i]){
                max=arr[i];
            }
        }
        return max;
    }
    
    int get(int i,int j){
        int sum;
        int x=0,y=0,z=0,p=0;
        //若已经得出轨迹长度,就无需再递归,因为temp已被递归过 
        if(temp[i][j]>0){
            return temp[i][j];
        }
        if(i>=1&&a[i][j]>a[i-1][j]){
            x=get(i-1,j)+1;
        }
        if(i<=m-2&&a[i][j]>a[i+1][j]){
            y=get(i+1,j)+1;
        }
        if(j>=1&&a[i][j]>a[i][j-1]){
            z=get(i,j-1)+1;
        }
        if(j<=n-2&&a[i][j]>a[i][j+1]){
            p=get(i,j+1)+1;
        }
        if(x||y||z||p){
            temp[i][j] = getMax(x,y,z,p);
        }else{
            temp[i][j] = 1;
        }
        return temp[i][j];
    }
    
    int main(){
        cin>>m>>n;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                cin>>a[i][j];
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                temp[i][j]=get(i,j);
            }
        }
        int max=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(temp[i][j]>max){
                    max=temp[i][j];
                }
            }
        }
        
        cout<<max<<endl;
        return 0;
    }
  • 相关阅读:
    129 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 02 懒汉式的代码实现
    128 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 01 饿汉式的代码实现
    127 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 02 单例模式概述 01 单例模式的定义和作用
    126 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 01 设计模式概述 01 设计模式简介
    125 01 Android 零基础入门 02 Java面向对象 05 Java继承(下)05 Java继承(下)总结 01 Java继承(下)知识点总结
    leetcode-----121. 买卖股票的最佳时机
    leetcode-----104. 二叉树的最大深度
    Json串的字段如果和类中字段不一致,如何映射、转换?
    Mybatis-Plus的Service方法使用 之 泛型方法default <V> List<V> listObjs(Function<? super Object, V> mapper)
    模糊查询
  • 原文地址:https://www.cnblogs.com/tz346125264/p/7575675.html
Copyright © 2011-2022 走看看