羊羊列队

时间限制: 1 Sec  内存限制: 128 MB

提交: 65  解决: 1

题目描述

在修建完新路后,小羊们总算可以安心入学了。今年是羊年,新入学的小羊特别多。老师们打算将N只小羊分成M个班级,每个班至少有1只羊。

如何分班成了老师们最头疼的事情,因为开学典礼上,村长就要看到小羊们列队的情况。每个班的小羊都排成一排,站在草场上。村长希望队列中羊的高度尽可能整齐,村长对队列的不整齐度有自己的要求。

例如队列中共有t只羊,高度依次为A1,A2……,At。那么不整齐度为:(|A1-A2|+|A2-A3|+……+|At-1-At|)2。即相邻两只羊高度差之和的平方。

而总体的不整齐度,就是各班不整齐度之和。

现在,请你帮助老师们设计一下,如何分班,如何列队,才能使M个班级的不整齐度之和最小。

输入

第一行两个整数N和M,分别表示共有N只小羊,要被分成M个班级。

第二行N个整数,表示每只小羊的高度Ai。

输出

输出最小的不整齐度之和,结果保证不会超过231-1。

样例输入



4 2

4 1 3 2


样例输出



2


提示

【样例解释】

分成两班,4和3一个班,1和2一个班,不管怎么排,两个班的不整齐度都是1,不整齐度之和为2。

【数据范围】

30%的数据,1<=N<=10;1<=M<=5;

80%的数据,1<=N<=300;1<=Ai<=1000;

100%的数据,1<=N<=10000,1<=M<=1000,1<=Ai<=1000000,保证M<=N。

 

思路:

/*

* s[i][j]表示第i只小羊到第j只小羊的不整齐度

* 分析:

* 状态:

* f[i][j]表示把i只小羊分到j个班级的最小不整齐度。

* 初始状态:

* f[i][1]=s[1][i],f[i][i]=0,f[i][0]=0,f[0][i]=0;

* 最终状态:

* f[n][m]

* 状态转移方程:

* k表示两个班级划分的点

* f[i][j]=min(f[i][j],f[k][j-1]+s[k+1][i]) (j-1<=k<i)

*

* dp过程:

* i...1->n

* j...i->i

* k...j-1->i-1

*

*/

 



1 /*
2 * s[i][j]表示第i只小羊到第j只小羊的不整齐度
3 * 分析:
4 * 状态:
5 * f[i][j]表示把i只小羊分到j个班级的最小不整齐度。
6 * 初始状态:
7 * f[i][1]=s[1][i],f[i][i]=0,f[i][0]=0,f[0][i]=0;
8 * 最终状态:
9 * f[n][m]
10 * 状态转移方程:
11 * k表示两个班级划分的点
12 * f[i][j]=min(f[i][j],f[k][j-1]+s[k+1][i]) (j-1<=k<i)
13 *
14 * dp过程:
15 * i...1->n
16 * j...i->i
17 * k...j-1->i-1
18 *
19 */
20 #include <bits/stdc++.h>
21 #define Maxn 305
22 #define Maxm 305
23 using namespace std;
24 void printArr_a();
25 void printArr_s();
26 void printArr_f();
27 void printArr_k_();
28 void printArr_classCheep();
29 void printArr_pre();
30 void printWay(int i,int j);
31 int f[Maxn][Maxm],a[Maxn],s[Maxn][Maxn];
32 int pre[Maxn][Maxm];
33 int k_[Maxn];//决策
34 int classCheep[Maxn][2];//每个班级里面的人数
35 int n,m;
36 //s[i][j]表示第i只小羊到第j只小羊的不整齐度
37 int main(){
38 freopen("src/in.txt","r",stdin);
39 cin>>n>>m;
40 for(int i=1;i<=n;i++) cin>>a[i];
41 sort(a+1,a+n+1);
42 //printArr_a();
43 //初始化s数组
44 for(int i=1;i<=n;i++){
45 s[i][i]=0;
46 int tmp=0;
47 for(int j=i+1;j<=n;j++){
48 tmp+=a[j]-a[j-1];
49 s[i][j]=tmp*tmp;
50 }
51 }
52 //printArr_s();
53 //dp操作
54 //------------------------------------------------------------
55 memset(f,0x1f,sizeof(f));
56
57 //初始化
58 for(int i=0;i<=n;i++){
59 f[i][1]=s[1][i];
60 f[i][i]=0;
61 f[i][0]=0;
62 f[0][i]=0;
63 for(int j=i+1;j<=n;j++){
64 f[i][j]=0;
65 }
66 }
67 //printArr_f();
68 for(int i=2;i<=n;i++){
69 for(int j=2;j<=m&&j<i;j++){
70 for(int k=j-1;k<i;k++){
71 //f[i][j]=min(f[i][j],f[k][j-1]+s[k+1][i]);
72 int tmp=f[k][j-1]+s[k+1][i];
73 if(tmp<f[i][j]){
74 f[i][j]=tmp;
75 k_[i]=k;
76 pre[i][j]=k;
77 classCheep[i][0]=k+1;
78 classCheep[i][1]=i;
79 }
80 }
81 }
82 }
83 // printArr_f();
84 // printArr_k_();
85 // printArr_classCheep();
86 // printArr_pre();
87 // printWay(9,4);
88 cout<<f[n][m]<<endl;
89 }
90
91
92
93 void printArr_a(){
94 cout<<"Arr_a"<<endl;
95 for(int i=1;i<=n;i++){
96 cout<<a[i]<<" ";
97 }
98 cout<<endl;
99 }
100 void printArr_s(){
101 cout<<"Arr_s"<<endl;
102 for(int i=1;i<=n;i++){
103 for(int j=1;j<=n;j++){
104 cout<<setw(5)<<s[i][j]<<" ";
105 }
106 cout<<endl;
107 }
108 }
109 void printArr_f(){
110 cout<<"Arr_f"<<endl;
111 for(int i=0;i<=n;i++){
112 for(int j=0;j<=m;j++){
113 cout<<setw(12)<<f[i][j]<<" ";
114 }
115 cout<<endl;
116 }
117 }
118 void printArr_k_(){
119 cout<<"Arr_k_"<<endl;
120 for(int i=1;i<=n;i++){
121 cout<<k_[i]<<" ";
122 }
123 cout<<endl;
124 }
125 void printArr_classCheep(){
126 cout<<"Arr_classCheep"<<endl;
127 for(int i=1;i<=n;i++){
128 cout<<"第"<<i<<"只羊: "<<classCheep[i][0]<<" "<<classCheep[i][1]<<endl;
129 }
130 cout<<endl;
131 }
132
133 void printArr_pre(){
134 cout<<"Arr_pre"<<endl;
135 for(int i=0;i<=n;i++){
136 for(int j=0;j<=m;j++){
137 cout<<setw(12)<<pre[i][j]<<" ";
138 }
139 cout<<endl;
140 }
141 }
142
143 void printWay(int i,int j){
144 if(j==0) return;
145 printWay(pre[i][j],j-1);
146 int start=pre[i][j]+1;
147 int end=i;
148 int k=0;
149 while(end-start){
150 cout<<a[start++]<<" ";
151 }
152 cout<<a[end]<<endl;
153 }