线性最佳分割算法

题目描述:

给出任意一个一维数组,数组中又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:\n");
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("\n");
48     }
49 
50     printf("Here is the d matrix:\n");
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("\n");
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

 

posted @ 2014-01-10 21:04  湖心北斗  阅读(1142)  评论(0编辑  收藏  举报