最大N段和问题

来源:互联网 发布:360软件商店 编辑:程序博客网 时间:2024/04/27 17:35
 

再也不盲目相信网上的程序了,今天看了一个网页的博克的递归式子,竟然是错的!害得我白白写了半天程序

下面的程序是我自己推到的递归式子 ,已经经过测试了,事对的!

/**
 * 【问题描述】
 * 给定由n个整数(可能为负整数)组成的序列a1,a2,…..an,(-100<=ai<=100),以及一个正整数m,
 * 要求确定序列a1,a2,…..an的m个不相交的子段,使这m个子段的总合达到最大。
 * 【输入】
 * 第一行:N,m。(1<=n <=1000,2<=m<=10)
 * 第二行:a1,a2,…..an。中间一个空格。
 * 【输出】
 * M个子段的最大和。
 * 【样例输入】
 * 10 2
 * -1 1 -2 3 4 -2 -5 5 6 7
 * 【样例输出】
 * 25
 * 问题分析:
 * 设f(i,j)为从1到i分成j段的最大的和,则动归方程:
 *f [i,j,0]:=max(f[i-1,j,1],f[i-1,j,0]);//前i个数,选j段,0是不取、1是取
 *f[i,j,1]:=max(f[i-1,j,1],f[i-1,j-1,0])}+w[i];
 */

/**
 * @author Administrator
 *
 */
public class MaxNSum {
    /**
     * 私有变量
     */
 private int[][][] f;
 private int[] w;
 private int n;
 private int m;
 /**
  * 构造函数
  */
 public MaxNSum(int[] w,int num,int m) {
  // TODO Auto-generated constructor stub
  this.w=w;
  this.n=num;
  this.m=m;
  f=new int[n+1][m+1][2];
 }
    /**
     * 动态规解决问题
     */
 public void maxNSum()
 {
  for(int i=1;i<=n;i++)
  {
   for(int j=1;j<=m;j++)
   {
    f[i][j][0]=f[i-1][j][1]>f[i-1][j][0]?f[i-1][j][1]:f[i-1][j][0];
    f[i][j][1]=f[i-1][j][1]>f[i-1][j-1][0]?f[i-1][j][1]+w[i-1]:f[i-1][j-1][0]+w[i-1];
   }
  }
  int max=0;
  for(int k=1;k<=m;k++)
  {
   if(f[n][k][0]>max)
   {
    max=f[n][k][0];
   }
   if(f[n][k][1]>max)
   {
    max=f[n][k][1];
   }
  }
  System.out.println(max);
 }
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
        int[] w={-1,1,-2,3,4,-2,-5,5,6,7};
        MaxNSum mn=new MaxNSum(w,10,2);
        mn.maxNSum();
 }

}

原创粉丝点击