题目大意:将n个数分成m组,将每组的最大值与最小值的平方差加起来,求最小和。

题目分析:先对数排序。定义状态dp(i,j)表示前 j 个数分成 i 组得到的最小和,则状态转移方程为dp(i,j)=min(dp(i,k-1)+w(k,j)),其中w(i,j)=(a[i]-s[j])*(a[i]-a[j])。很显然,dp(i,j)满足凸四边形不等式。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; const int INF=1<<30;
int dp[10005][505];
int K[10005][505];
int a[10005];
int n,m; void read()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",a+i);
} int solve()
{
sort(a+1,a+n+1);
for(int i=1;i<=n;++i){
dp[1][i]=(a[i]-a[1])*(a[i]-a[1]);
K[1][i]=0;
if(i<=m){
dp[i][i]=0;
K[i][i]=i;
}
}
for(int i=2;i<=m;++i){
K[i][n+1]=n;
for(int j=n;j>=i;--j){
dp[i][j]=INF;
for(int k=K[i-1][j];k<=K[i][j+1];++k){
if(dp[i][j]>dp[i-1][k-1]+(a[j]-a[k])*(a[j]-a[k])){
dp[i][j]=dp[i-1][k-1]+(a[j]-a[k])*(a[j]-a[k]);
K[i][j]=k;
}
}
}
}
return dp[m][n];
} int main()
{
int T,cas=0;
scanf("%d",&T);
while(T--)
{
read();
printf("Case %d: %d\n",++cas,solve());
}
return 0;
}

  

最新文章

  1. Worktile协同特色之二:任务看板管理
  2. Nginx配置文件说明
  3. Extjs API - JS Duck
  4. c++性能测试
  5. Hyper Prefix Sets
  6. windows环境搭建jira 详解
  7. trycatch放在for循环的里面还是外面好
  8. vue-cli脚手架npm相关文件解读(5)vue-loader.conf.js
  9. js的继承实现
  10. 《前端之路》之五 head 头标签指南
  11. 查看 FormData 中已存在的值
  12. 举例跟踪linux内核系统调用
  13. Win2008服务启动不能调用Office Word的解决方法
  14. CF1101G (Zero XOR Subset)-less
  15. 『TensorFlow Internals』笔记_源码结构
  16. First C++
  17. 读jQuery源码释疑笔记
  18. 开源项目MultiChoiceAdapter详解(四)——MultiChoiceBaseAdapter的使用
  19. c#使用QQ邮箱的SSL收发邮件
  20. 学习 Linux,302(混合环境): 概念

热门文章

  1. shell字符串操作技巧
  2. kafka生产者和消费者
  3. ELK学习笔记之CentOS 7下ELK(6.2.4)++LogStash+Filebeat+Log4j日志集成环境搭建
  4. bzoj1660 / P2866 [USACO06NOV]糟糕的一天Bad Hair Day
  5. Python descriptor 以及 内置property()函数
  6. 使用CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件
  7. 20145302张薇 《网络对抗技术》 web基础
  8. 将kali linux装入U盘 制作随身携带的kali linux
  9. mips32和x86下的大小端模式判定
  10. PHP开发者的路书