把n个数分成m段,每段的值为(MAX - MIN)2,求所能划分得到的最小值。

依然是先从小到大排个序,定义状态d(j, i)表示把前i个数划分成j段,所得到的最小值,则有状态转移方程:

d(j, i) = min { d(j-1, k) + (ai - ak+1)2 | 0 ≤ k < i }

设 l < k < i,且由k转移得到的状态比由l转移得到的状态更优。

有不等式:

整理成斜率形式:

后面的就可以相当于套模板了,不过这里要用滚动数组优化一下空间。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int maxm = + ;
const int INF = 0x3f3f3f3f; int n, m; int a[maxn];
int d[][maxn]; int head, tail;
int Q[maxn]; int cur; int inline Y(int x) { return d[cur^][x] + a[x+] * a[x+]; } int inline DY(int p, int q) { return Y(q) - Y(p); } int inline DX(int p, int q) { return a[q+] - a[p+]; } int main()
{
freopen("in.txt", "r", stdin); int T; scanf("%d", &T);
for(int kase = ; kase <= T; kase++)
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) scanf("%d", a + i);
sort(a + , a + + n); memset(d[], 0x3f, sizeof(d[]));
d[][] = ;
cur = ;
for(int i = ; i <= m; i++)
{
cur ^= ;
head = tail = ;
Q[tail++] = ;
for(int j = ; j <= n; j++)
{
while(head + < tail && DY(Q[head], Q[head+]) <= DX(Q[head], Q[head+]) * * a[j]) head++;
while(head + < tail && DY(Q[tail-], j) * DX(Q[tail-], Q[tail-]) <= DY(Q[tail-], Q[tail-]) * DX(Q[tail-], j)) tail--;
Q[tail++] = j;
d[cur][j] = d[cur^][Q[head]] + (a[j]-a[Q[head]+]) * (a[j]-a[Q[head]+]);
}
}
printf("Case %d: %d\n", kase, d[cur][n]);
} return ;
}

代码君

下面是四边形不等式优化的代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int maxm = + ;
const int INF = 0x3f3f3f3f; int n, m; int a[maxn];
int d[maxm][maxn], s[maxm][maxn]; int main()
{
int T; scanf("%d", &T);
for(int kase = ; kase <= T; kase++)
{
scanf("%d%d", &n, &m); for(int i = ; i <= n; i++) scanf("%d", a + i);
sort(a + , a + + n); memset(s, , sizeof(s));
for(int i = ; i <= m; i++)
{
int j;
for(j = ; j <= i; j++) d[i][j] = ;
for(; j <= n; j++) d[i][j] = INF;
} for(int i = ; i <= n; i++)
{
s[][i] = ;
d[][i] = (a[i] - a[]) * (a[i] - a[]);
} for(int i = ; i <= m; i++)
{
s[i][n+] = n;
for(int j = n; j > i; j--)
{
for(int k = s[i-][j]; k <= s[i][j+]; k++)
{
int t = d[i-][k] + (a[j] - a[k+]) * (a[j] - a[k+]);
if(t < d[i][j])
{
d[i][j] = t;
s[i][j] = k;
}
}
}
} printf("Case %d: %d\n", kase, d[m][n]);
} return ;
}

代码君

最新文章

  1. 从零开始编写自己的C#框架(11)——创建解决方案
  2. QML杂记
  3. N-Tier Entity Framework开源项目介绍
  4. Spring Framework------&gt;version4.3.5.RELAESE-----&gt;Reference Documentation学习心得-----&gt;使用Spring Framework开发自己的应用程序
  5. JS 打印功能代码可实现打印预览、打印设置等
  6. poj3241 曼哈顿最小距离生成树第k大的边
  7. yield学习续:yield return迭代块在Unity3D中的应用——协程
  8. uploadify上传控件使用
  9. Linq 的IQueryable和IEnumerable方式
  10. PDO封装函数
  11. ExternalInterface的简单使用方法
  12. osgEarth基础入门(转载)
  13. Kafka思维导图
  14. jmeter4.x centos7部署笔记
  15. dockerd启动配置_修改IP和systemd管理
  16. Java SubString截取字符串
  17. Codeforces Round #512 (Div. 2) D. Vasya and Triangle
  18. 大数据学习路线之linux系统基础搭建
  19. QuickHit 项目
  20. 吴裕雄 20-MySQL NULL 值处理

热门文章

  1. JS中的关系操作符与自动转型
  2. 关于IO模拟时序(SPI)的注意事项
  3. Unity Shader入门精要学习笔记 - 第11章 让画面动起来
  4. CSS3在hover下的几种效果
  5. Spring框架学习——AOP的开发
  6. cvCanny的参数
  7. PHP小数处理常用函数
  8. 【Web应用-网络连接】Azure Web 应用对外连接数上限分析
  9. C++实现动态数组
  10. Ajax 发送OPTION请求