1.礼物的最大价值
思路一:利用动态规划的思想,先用递归的思路分析。先定义第一个函数f(i,j)表达能到达坐标f(i,j)的格子时能拿到礼物总和的最大值。根据题目要求,有两种可能的途径到达坐标为(i,j)的格子。因此的状态转移方程为f(i,j)=max(f(i-1,j),f(i,j-1))+gift[i,j]

    int getMaxValue_solution1(const int*values,int rows,int cols)
    {
        if(values==nullptr||rows<=0||cols<=0)
        {
            return 0;//特殊情况
        }
        int **maxValues=new int*[rows];
        for(int i=0;i<rows;i++)
        {
            maxValues[i]=new int[cols];
        }
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                int left=0;
                int up=0;
                if(i>0)
                up=maxValues[i-1][j];
                if(j>0)
                left=maxValues[i][j-1];//特殊条件
                maxValues[i][j]=max(left,up)+values[i*cols+j];//状态转移方程
            }
        }
        int maxValue=maxValues[rows-1][cols-1];//最后的值就是矩阵右下角的值
        for(int i=0;i<rows;++i)
        {
            delete[] maxValues[i];
        }
        delete maxValues;
        return maxValue;
    }

思路二:考虑进一步的优化,因为到达坐标为(i,j)的格子时能够拿到的礼物的最大价值只与两个格子有关,即(i-1,j)与(i,j-1),因此第i-2行及更上面的所有格子礼物的最大价值实际没必要保存。可以利用一个一维数组来代替上述的二维矩阵。改一维数组的长度为棋盘的列数n。当计算到(i,j)的格子时能够拿到最大价值为f(i,j),数组前j个数字分别是f(i,0)到f(i,j-1),数组从下标为j的数字开始到最后一个数字,分别为f(i-1,j)到f(i-1,n-1),也就是说,该数组前面j个数字分别是当前第i行前面j个格子礼物的最大价值,而之后的数字分别保存前面第i-1行n-j个格子礼物的最大价值。

    int getMaxValue_solution1(const int*values,int rows,int cols)
    {
        if(values==nullptr||rows<=0||cols<=0)
        {
            return 0;//特殊情况
        }
        int *maxValues=new int[cols];
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                int left=0;
                int up=0;
                if(i>0)
                up=maxValues[j];
                if(j>0)
                left=maxValues[j-1];
                maxValues[i][j]=max(left,up)+values[i*cols+j];//状态转移方程
            }
        }
        int maxValue=maxValues[cols-1];//最后的值就是最右面的值
        delete maxValues;
        return maxValue;
    }
};