微信扫一扫打赏支持

羊羊列队

羊羊列队

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

 

posted @ 2017-08-24 06:14  范仁义  阅读(1014)  评论(0编辑  收藏  举报