动态规划之收集苹果

路径经过的最大值(最小值):
原题:平面上有N*M个格子,每个格子中放着一定数量的苹果。从左上角的格子开始, 每一步只能向下走或是向右走,每次走到一个格子就把格子里的苹果收集起来, 这样一直走到右下角,问最多能收集到多少个苹果。

不妨用一个表格来表示:

{5, 8, 5, 7, 1, 8},
    {1, 3, 2, 8, 7, 9},
    {7, 8, 6, 6, 8, 7},
    {9, 9, 8, 1, 6, 3},
    {2, 4,10, 2, 6, 2},
    {5, 5, 2, 1, 8, 8},

在这个6X6的表格里面填写了一些数表示所在格子中的苹果数量。根据题目的规则"每一步只能向下走或是向右走",如果用x表示纵向,用y表示横向,那么能够到达a[x,y]处的只有两个位置a[x-1,y](上一格)和a[x,y-1](左边一格),所以必然是取这两个位置中比较大的那一个点。依此回溯到a[0,0],或者从a[0,0]递推到a[x,y]。

......... , ......... , a[x-1,y]

......... , a[x,y-1], a[x,y] ,

基于这一点,我们可以从左上角开始将到达第一行和第一列中各点所能收集到的最大苹果数量填成一张表格。如下:

接下来填第2行,首先是第2行第2列的值,应该填写为 MAX(A[1,2], A[2,1])+ A[2,2]对应的苹果数量。也就是说到达第2行第2列能获得的最大苹果数,要看第2行第1列所获得的苹果数(6)和第1行第2列所获得的苹果数(13),这两者哪个更大,谁大就取谁的值,显然第1行第2列所获得的苹果数(13)更大,所以用13加上第2行第2列的苹果数3 = 16,就是到达第2行第2列能获得的最大苹果数。同理,填所在格能获得的最大苹果数就是看它左面一格和上面一格哪个值更大,就取哪个值再加上自己格子里面的苹果数,就是到达此格能获得的最大苹果数。依此填完所有格子,最后得到下图:

所以:到达右下角能够获得的最大苹果数量是76。所经过的路径可以通过倒推的方法得到,从右下角开始看所在格子的左边一格和上面一格哪边大就往哪边走,如果遇到一样大的,任选一条即可。

这样我们可以画出路线图,如下图右边表格:

这个例子的分析和解决方法大概就是这样了。在前面第一个例子里面我们提到:空间换时间是动态规划的精髓。但是一个问题是否能够用动态规划算法来解决,需要看这个问题是否能被分解为更小的问题(子问题)。而子问题之间是否有包含的关系,是区别动态规划算法和分治法的所在。一般来说,分治法的各个子问题之间是相互独立的,比如折半查找(二分查找)、归并排序等。而动态规划算法的子问题在往下细分为更小的子问题时往往会遇到重复的子问题,我们只处理同一个子问题一次,将子问题的结果保存下来,这就是动态规划的最大特点。

动态规划算法总结起来就是两点:

1 寻找递推(递归)关系,比较专业的说法叫做状态转移方程。

2 保存中间状态,空间换时间。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SeqListSort
{
    /// <summary>
    /// <ather>
    /// lihonglin
    /// </ather>
    /// <content>
    /// 平面上有N*M个格子,每个格子中放着一定数量的苹果。你从左上角的格子开始,每一步只能向下走或是
    /// 向右走,每次走到一个格子上就把格子里的苹果收集起来,这样一直走到右下角,你最多能收集到多少个苹果。
    ///输入:
    ///第一行输入行数和列数
    ///随机产生每个格子的中的苹果的数量
    ///输出:最多能收到的苹果的个数。
    ///
    ///思路分析:这是一个典型的二维数组DP问题
    ///基本状态:当你到达第x行第y列的格子的时候,收集到的苹果的数量dp[x,y]。
    ///转移方程:由于你只能向右走或者向下走,所以当你到达第x行第y列的格子的时候,你可能是从第x-1行第
    ///y列或者第x行第y-1列到达该格子的,而我们最后只要收集苹果最多的那一种方案。
    ///所以:dp[x,y] = max( if(x>0) dp[x-1,y] , if(y>0) dp[x,y-1])
    /// </content>
    /// </summary>
    class Apple_DP
    {
        static int[,] a = new int[100,100];
        static int[,] dp = new int[100,100];
        static int m,n;

        static void CollectApple(int x,int y)
        {
            dp[x, y] = a[x, y];
            int max = 0;
            if (x > 0 && max < dp[x - 1, y])// 上边一格 终点是x,y
            {
                max = dp[x - 1, y];
            }
            if (y > 0 && max < dp[x, y - 1])// 左边一格 终点是x,y
            {
                max = dp[x, y - 1];
            }
            dp[x, y] += max;
            if(x < m - 1)
            {
                CollectApple(x + 1, y);
            }
            if(y < n - 1)
            {
                CollectApple(x, y + 1);
            }
        } 

        public static void InitMap()
        {
            Console.WriteLine("请输入m行,n列");
            m = Convert.ToInt32(Console.ReadLine());
            n = Convert.ToInt32(Console.ReadLine());
            Random r = new Random();
            for(int i=0;i<m;i++)
            {
                for(int j=0;j<n;j++)
                {
                    //a[i,j] = r.Next(1,m + n);
                    Console.Write("{0,-3}", a[i, j] = r.Next(1, m + n));
                }
                Console.WriteLine();
            }
            CollectApple(0, 0);
            // 打印结果
            for(int i=0;i<m;i++)
            {
                for(int j=0;j<n;j++)
                {
                    Console.Write("{0,-3}", dp[i, j]);
                }
                Console.WriteLine();
            }
        }
    }
}
时间: 2024-11-08 18:55:30

动态规划之收集苹果的相关文章

《收集苹果》 动态规划入门

问题描写叙述 平面上有N*M个格子,每一个格子中放着一定数量的苹果.你从左上角的格子開始,每一步仅仅能向下走或是向右走,每次走到一个格子上就把格子里的苹果收集起来,这样下去,你最多能收集到多少个苹果. 输入: 第一行输入行数和列数 然后逐行输入每一个格子的中的苹果的数量 输出: 最多能收到的苹果的个数. 思路分析 这是一个典型的二维数组DP问题 基本状态: 当你到达第x行第y列的格子的时候,收集到的苹果的数量dp[x][y]. 转移方程: 因为你仅仅能向右走或者向下走,所以当你到达第x行第y列的

动态规划之分苹果

题目描述:将M个苹果放置到N个盘子中,可以有盘子为空,但是不分顺序,例如5个苹果分到3个盘子中,1+1+3和1+3+1视为同一种方法,求所有的方法总数. ****动态规划***** import java.util.Scanner; 2 public class Main{ 3 public static void main(String[] args) 4 { 5 /* 6 *以dp[i][j]表示i个苹果放置到j个盘子的方法数 7 *i个苹果放到j个盘子中(不分顺序)分为两种情况 8 *1.

动态规划——奶牛接苹果

参考:http://blog.sina.com.cn/s/blog_61034ad90100encg.html f[i][j]表示i时刻移动j次的情况,f[i][j] = Max(f[i - 1][j], f[i - 1][j - 1]) + int(a[i] == (j + 1) % 2)  表示这种情况下,接到最多苹果为在上一时刻的情况下,此次不移动和移动的最大值,再加上当前的位置是否处在新出现的水果树下. // Study.cpp: 定义控制台应用程序的入口点. // #include "

动态规划-1620. 收集硬币

2020-04-08 07:45:18 问题描述: 给定一个n * m个的矩阵,矩阵的每个位置有一定数量的硬币,你从(0,0)位置出发,每次只能往右或者往下走,当他经过某个格子的时候,可以得到这个格子上的所有硬币,当它走到第(n-1,M-1)位置时游戏结束,在游戏开始前,你有?次机会,可以交换某两个格子中的硬币数量中,k次机会不一定要使用完,求从(0,0)走到第(n-1,M-1)所能得到的最大的硬币数量. 样例 输入: matrix = [[9,9,9,0,0],[0,0,9,0,0],[0,0

DP,得到最多苹果,(POJ2385)

题目链接:http://poj.org/problem?id=2385 题意: 牛在两棵苹果树下收集苹果,牛只能在这两棵树之间走动w次,在t时刻,某棵树会掉下苹果. 解题报告: ///dp[t][w]表示1~t秒内,转w次能够获得的最多苹果数目 ///状态转移方程 dp[t][w]=max(dp[t-1][w],dp[t-1][w-1]) #include <stdio.h> #include <string.h> #include <algorithm> using

Codeforces Round #312 (Div. 2) ABC题解

[比赛链接]click here~~ A. Lala Land and Apple Trees: [题意]: AMR住在拉拉土地.拉拉土地是一个非常美丽的国家,位于坐标线.拉拉土地是与著名的苹果树越来越随处可见. 拉拉土地恰好n苹果树.树数i位于位置xi和具有人工智能的苹果就可以了增长.阿姆鲁希望从苹果树收集苹果. AMR目前维持在X =0的位置.在开始的时候,他可以选择是否去左边或右边.他会在他的方向继续下去,直到他遇见一棵苹果树,他之前没有参观.他会采取所有的苹果,然后扭转他的方向,继续走这

动态规划网络资料收集

之前在学习如何写hoj 1003 的时候,由于不懂动态规划,所以把动态规划相关内容智力学习了一下,虽然对我来说,学会1003和看明白跟动态规划没有什么比较大的关系,但对之前收集的资料做一下整理也好. 首先,什么是动态规划,如何理解动态规划 知乎徐凯强的答案很有“总纲”的感觉 https://www.zhihu.com/question/23995189/answer/35324479 王勐 也说的很清楚 https://www.zhihu.com/question/23995189/answer

m个苹果放在n个盘子里面有多少种放法?(动态规划)

m个苹果放在n个盘子里面有多少种放法?(动态规划) 实现代码如下: #include <iostream> using namespace std; int s(int m ,int n) { if(m==0||n==1){ return 1; } if(m<n) { return s(m,m); } if(m>=n) { return s(m, n - 1) + s(m - n, n); } return 0; } int main() { int m,n; while(cin&

苹果新的编程语言 Swift 语言进阶(四)--字符串和收集类型

一.字符串( String  )和字符类型(Character) 字符串是一种字符的带次序的收集类型(相当于数组),字符是字符串中的元素. 在Swift 语言中,字符串是编码独立的Unicode字符的组合,并提供相应方法来获取以各种Unicode呈现方式包含的字符. 1. 字符串定义和初始化 Swift 语言使用var或let关键字来定义一个常量字符串(不可修改)或变量字符串(可以修改).  而不是像Object C语言一样定义两种不同的类型. Swift 语言允许使用一个双引号的字符串来初始化