动态规划问题三简单理解——剪绳子

问题说明

给你一根长度为n的绳子,请把绳子剪成整数长度的m段(m,n都是整数,n>1,m>1),每段绳子的长度记为k[0],k[1]…k[m]。请问k[0],k[1]…k[m]可能的最大乘积是多少?例如当绳子长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18。

问题解释
  1. 一条长为n的绳子最多被切n-1
  2. 当切完第m次后,它都会利用到前面m-1次的线段乘积,也就是说我们可以把最后一次切下的地方约定下来,这样我们只需求得前m-1次切绳的最大乘积
思路分析
  1. 创建数组cut[n][n]
  2. cut[i][j]:表示一共切了i刀最后一刀落在第j的位置上
  3. i=0或者j=0时,cut[i][j]没有意义,因为切0刀或者落在第0的位置是没有意义的。
  4. i=1时,也就是说只切一刀的时候,绳子被切成两半,右边部分暂且不管,左边部分的长度就等于j
  5. i=j的时候,切了i刀,最后一刀落在第i位置上,也就是说,每一刀都是切成1单位长度(只管左边,右边暂且不管),所以cut[i][i]=1
  6. 那么对于数组中其他的值如何确定呢?
    • 举例:cut[2][3]:切了2刀,第2刀切在第3位置上
    • 那么第一刀可能切在第2位置上,也可能切在第1位置上,即:第一刀可能是cut[1][2]和cut[1][1],我们只需要比较**cut[1][2]×(3-2)cut[1][1]×(3-1)**的值,取最大值即是cut[2][3]的值
    • 对于其他的cut[i][j],它的值等于cut[i-1][j-1]×(1)cut[i-1][i-1]×(j-i+1) 中的最大值.
cut[i][j]赋值代码
//cut数组赋值,i=0或j=0没有意义
        for(int i=1;i<n;i++){
            for(int j=i;j<n;j++){
                if(i==1)    cut[i][j]=j;
                else if(i==j)
                    cut[i][j]=1;
                else{
                    //填充数组主要部分
                    int max = 0;
                    for(int t=j-1;t>=i-1;t--){
                        if(cut[i-1][t]*(j-t)>max)
                            max = cut[i-1][t]*(j-t);
                    }
                    cut[i][j]=max;
                }
            }
        }
发布了11 篇原创文章 · 获赞 1 · 访问量 421

猜你喜欢

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