• 线性最佳分割算法


    题目描述:

    给出任意一个一维数组,数组中又m个数,在不改变数顺序的前提下,将数分割成尽量相等的k份。

    动态规划
     动态规划方程式:f[i,j]=min(max(f[x,j-1],p[i]-p[x]));即i个数分成j份,他们的最佳分割值的大小是分成j-1份之中所有最佳
     可能性得值和后继所有元素之和的最大值中的最小值。
     为什么呢?
     第一步,我们简单的看一个数组分成两份的情况。
     把一个数组a[10]平均分成两份假设元素分别是1,2,3,4,5
     则算法如此运行:
     1| 2 3 4 5    maxvalue:14.
     1 2| 3 4 5    maxvalue:12
     1 2 3| 4 5    maxvalue:9
     1 2 3 4| 5    maxvalue:10
     因此最佳分割是1 2 3和4 5
     第二步,我们假设数组分成三份
     1 2 3 4 5
     按照算法就会遍历x个元素分成2组所有的最佳情况,和后续元素组成3组
     数组     分割点       组1 2  3  max
     1         1         0  1  14 14
     1 2       2         1  2  12 12
     1 2 3     3         3  3  9   9
     1 2 3 4   4         6  4  5   6
     1 2 3 4 5 5         6  9  0   9
     取最大值的最小值
     于是分成三组的最佳分割就是 1 2 3| 4| 5
     任意多个元素的情况下,只要记录下x个元素的j-1分割所有最佳情况,就可以计算出i个元素分成j组的最佳情况。
     算法设计:
     使用m[i][j]记录所有状态:i个元素分成j组的最佳分割值(每组元素之和的最大值)
     初始化:
     m[i][1]表示了a[1]~a[i]元素的前缀和i个元素分成1组就是本身
     m[1][i]表示 a[i]
     计算m[i][j] 就必须先求出m[x][j-1]和p[i]-p[x]的所有最大值中的最小值
     于是如此地推下去
     d[i][j]记录下当i个元素分成j份的时候分割的地方在哪里,也就是数组下标。

     1 #include <stdio.h>
     2 #define INF 1000000000
     3 int a[100],p[100];
     4 int m[100][100];
     5 int d[100][100];
     6 int n,k;
     7 int max(int p1,int p2)
     8 {
     9     return p1<p2?p2:p1;
    10 }
    11 void partition()
    12 {
    13     //计算出前缀和 填充 矩阵m
    14     int i,j,x;
    15     p[0]=0;
    16     for(i=1;i<=n;i++)
    17     {
    18         p[i]=p[i-1]+a[i];
    19     }
    20     for(i=0;i<=n;i++)for(j=0;j<=n;j++)d[i][j]=-1;
    21     for(i=1;i<=n;i++)m[i][1]=p[i];
    22     for(i=1;i<=n;i++)m[1][i]=a[i];
    23     for(i=2;i<=n;i++)
    24     {
    25         for(j=2;j<=k;j++)
    26         {
    27             m[i][j]=INF;
    28             for(x=1;x<=i-1;x++)//在i-1个元素中寻找分割点
    29             {
    30                 if(x<j)continue;
    31                 int s=max(m[x][j-1],p[i]-p[x]);//寻找分成可能包含余下全部元素
    32                 if(m[i][j]>s)
    33                 {
    34                     m[i][j]=s;//x个元素 分成 j份的最大值=i个元素分成j-1份的最大值 或者是余下的数组成的最大值
    35                     d[i][j]=x;//
    36                 }
    37             }
    38         }
    39     }
    40     printf("Here is the m matrix:
    ");
    41     for(i=0;i<=n;i++)
    42     {
    43         for(j=0;j<=n;j++)
    44         {
    45             printf("%d ",m[i][j]);
    46         }
    47         printf("
    ");
    48     }
    49 
    50     printf("Here is the d matrix:
    ");
    51     for(i=0;i<=n;i++)
    52     {
    53         for(j=0;j<=n;j++)
    54         {
    55             printf("%d ",d[i][j]);
    56         }
    57           printf("
    ");
    58     }
    59 }
    60 int main(int argc, const char * argv[])
    61 {
    62 
    63     // insert code here...
    64     int i;
    65     scanf("%d",&n);
    66     scanf("%d",&k);
    67     a[0]=0;
    68     for(i=1;i<=n;i++)
    69     {
    70         scanf("%d",&a[i]);
    71     }
    72     partition();
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    java的继承---包装器与自动装箱
    linux开机启动过程,很多人说的不太清楚的看看。
    黑盒测试/三角形(OC)
    git 忽略一些文件的提交
    volley 框架的使用
    如何通过阿里百川的集成,以及manifest的权限配置完成淘客商品详情页的链接
    抓取网站访问者的QQ号码
    写写东西吧
    Android 强制实现下线功能
    Android 新闻显示界面且适应平板
  • 原文地址:https://www.cnblogs.com/jackwuyongxing/p/3514479.html
Copyright © 2020-2023  润新知