动态规划问题一帮助理解

问题说明

 * 有 n 个学生站成一排,每个学生有一个能力值,
 * 牛牛想从这 n 个学生中按照顺序选取 k 名学生,
 * 要求相邻两个学生的位置编号的差不超过 d,
 * 使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?

为了方便理解,我们假设每个学生的能力值都是正数

  • 一共有n个学生,我们用正整数数组arr[n]表示

  • 需要在n个学生中找到k个人的问题其实可以理解为:

    1. 已经找到了最后一个人的位置
    2. 再找到前面k-1个人的位置即可
  • 不妨用一个select[k][n]数组表示

    1. select[i][j]:表示一共选择了i+1个人,且最后一人位置在j时的乘积
  • 那么select[i][j]该怎么表示呢?

    1. 我们可以知道select[0][0] ~ select[0][n-1]表示只选择一个人且这个人位置在任意时的乘积,
      select[0][0]的值是等于arr[0]的,同理select[0][j]=arr[j]
      • 也就是当我们画出select数组时,select[0]这一行的所有数据都可以确定
        我们假设arr={5,2,3,8,1},n=5,k=3,d=2
        在这里插入图片描述 2. 再来看第二行,select[1][0]表示选择了2个学生,最后一个位置为第0号,显然不可能,select[1][0]的值没有意义,同理 第i行前i个数据都无意义
        在这里插入图片描述 3. 那么其余数怎么确定呢?
      • 举个例子,select[1][1]表示选择2个人,第二个人在1号位置
        那么只可能一种情况,0号位置和1号位置都被选择了,那么select[1][1]=arr[1]*select[0][0]
      • 那么如果是select[1][2]的值如何确定?
        selec[1][2]表示选择2个人,最后一个人位置在第2号位置上
        它的值是依赖于除最后人外前面所有人的位置,即依赖于:select[0]这一行
        最后一人在第2号位置上,那么它前面一人就会落在【2-d,2-1】位置间,即:select[0][0]到select[0][1]这个区间,
        在这个区间内前一个人都可以落脚。
        找到这个区间内使得select[0](前一个人落脚)最大值,再乘以arr[j]得出select[1][2]的值
        在这里插入图片描述
    2. 所以具体确定select数组的值代码为
`//从select[1]到select[k-1]
        for(int i=1;i<k;i++){
            //第一个有值的地方开始,计算
            for(int j=i;j<n;j++){
        //select[1][1]=max(select[1-1][1-1],..,select[1-1][1-d])*arr[1]
                //不能越界,选择select[i-1]中的最大值
                int max=0;
                for(int t=j-1;t>=Math.max(0,j-d);t--){
                    if(select[i-1][t]>max)
                        max=select[i-1][t];
                }
                select[i][j]=max*arr[j];

            }
        }`
* 最后在select数组最后一行select[k-1]行中找到最大值即可
发布了11 篇原创文章 · 获赞 1 · 访问量 427

猜你喜欢

转载自blog.csdn.net/hhhghh_/article/details/104749722
今日推荐