羊羊列队
时间限制: 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 }