• 礼物的最大价值


    题目

      在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格,知道到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿多少价值的礼物?

    思路

    一、利用循环的动态规划

    1. 定义f(i,j)表示到达坐标为(i,j)的格子时能拿到的礼物总和的最大值;
    2. 有两种路径到达(i,j):(i-1,j)或者(i,j-1);
    3. f(i,j) = max(f(i-1,j), f(i,j-1)) + gift[i,j];
    4. 使用循环来计算避免重复子问题。

    二、优化空间复杂度,使用一维数组

      每次计算拿到的礼物最大值的时候,最大值的坐标只依赖(i-1,j)and(i,j-1)两个格子,因此第i-2行及以上所有的格子礼物最大值没有必要保存下来,因此可以用一维数组代替二维数组,一维数组的长度为棋盘的列数,当我们计算坐标为(i,j)格子能够拿到礼物的最大价值f(i,j)的时候,数组钱j个数字分别是f(i,0),f(i,1)...,f(i,j-1),数组从下标为j的数字开始到最后一个数字,分别为f(i-1,j),f(i-1,j+1),...,f(i-1,n-1),也就是数组前面j个数字分别是当前第i行前面j个格子礼物的最大值,而后的数字分别保存前面第i-1行n-j个格子礼物的最大值。

    1.

    class Solution
    {
        public:
            int get_max_value(const vector<vector<int> > &v);
    };
    int Solution::get_max_value(const vector<vector<int> > &v)
    {
        if(v.empty()||v.size()<=0||v[0].size()<=0)
            return -1;
    
        vector<vector<int>> maxValue(v.size(),vector<int>(v[0].size(),0));
        for(int i=0;i<v.size();++i)
        {
            for(int j=0;j<v.at(0).size();++j)
            {
                int up=0;
                if(i>0)
                    up=v.at(i-1).at(j);
    
                int left=0;
                if(j>0)
                    left=v.at(i).at(j-1);
    
                maxValue.at(i).at(j)=max(up,left)+v.at(i).at(j);
            }
        }
        return maxValue.at(v.size()-1).at(v.at(0).size()-1);
    }

    2.

    #include <iostream>
    #include <vector>
    #include <fstream>
    using namespace std;
    
    class Solution
    {
        public:
            int get_max_value(const vector<vector<int> > &v);
    };
    int Solution::get_max_value(const vector<vector<int> > &v)
    {
        if(v.empty()||v.size()<=0||v[0].size()<=0)
            return -1;
        
        //保存每一步拿到的礼物的最大值
        //每次计算拿到的礼物最大值的时候,最大值的坐标只依赖(i-1,j)and(i,j-1)两个格子,因此第
        //i-2行及以上所有的格子礼物最大值没有必要保存下来,因此可以用一维数组代替二维数组,
        //一维数组的长度为棋盘的列数,当我们计算坐标为(i,j)格子能够拿到礼物的最大价值f(i,j)的
        //时候,数组钱j个数字分别是f(i,0),f(i,1)...,f(i,j-1),数组从下标为j的数字开始到最后一个
        //数字,分别为f(i-1,j),f(i-1,j+1),...,f(i-1,n-1),也就是数组前面j个数字分别是当前第i行
        //前面j个格子礼物的最大值,而后的数字分别保存前面第i-1行n-j个格子礼物的最大值 
        vector<int> value(v[0].size(),0);
        for(int i=0;i<v.size();++i)
        {
            for(int j=0;j<v[0].size();++j)
            {
                int left=0;
                int up=0;
                
                if(i>0)
                    up=value[j];
                if(j>0)
                    left=value[j-1];
                    
                value[j]=max(up,left)+v[i][j];
            }
        }
        return value[v[0].size()-1];
    }
    
    int main()
    {
        ifstream in("1.txt");
        vector<vector<int> > v(4,vector<int>(4,0));
        for(int i=0;i<4;++i)
            for(int j=0;j<4;++j)
                in>>v[i][j];
        
        Solution s;
        cout<<s.get_max_value(v)<<endl;
        return 0;
    }
  • 相关阅读:
    【C# 调用 Go 语言】
    Go语言多线程 (转)
    CodeSoft 2019 企业版打标签
    (转)FFT求频谱图和功率谱密度图
    使用NI-DAQmx进行振动数据采集
    CentOS7 安装配置笔记
    .net 调用 nsfwjs 进行视频鉴别
    Electron.Net + Linux + Blazor 初尝备忘录
    关于feign调用的时候,动态传url ,以及自定义head
    go使用excelize导出xls
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10257677.html
Copyright © 2020-2023  润新知