题意:n个数之间放m个障碍,分隔成m+1段。对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小。

设:

d(i, j)表示前i个数之间放j个炸弹能得到的最小值

sum(i)为前缀和,cost(i)为前i个数两两相乘之和。

则有状态转移方程:

设0 ≤ l < k < i,且k比l更优,有不等式:

整理得到,注意不等号方向:

最后变成了斜率的形式,下面就用一个队列维护即可。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ; int n, m; int sum[maxn], cost[maxn];
int d[maxn][maxn]; int head, tail;
int Q[maxn]; int j; int inline Y(int i)
{
return d[i][j-] + sum[i] * sum[i] - cost[i];
} int inline DY(int x1, int x2) { return Y(x2) - Y(x1); } int inline DX(int x1, int x2) { return sum[x2] - sum[x1]; } int inline DP(int x1, int x2) { return d[x1][j-] + cost[x2] - cost[x1] - sum[x1]*(sum[x2]-sum[x1]); } int main()
{
while(scanf("%d%d", &n, &m) == && n)
{
for(int i = ; i <= n; i++) scanf("%d", sum + i);
for(int i = ; i <= n; i++) sum[i] += sum[i - ];
for(int i = ; i <= n; i++) cost[i] = cost[i-] + (sum[i]-sum[i-])*sum[i-]; for(int i = ; i <= n; i++) d[i][] = cost[i];
for(j = ; j <= m; j++)
{
head = tail = ;
Q[tail++] = ;
for(int i = ; i <= n; i++)
{
while(head + < tail && DY(Q[head], Q[head+]) <= sum[i] * DX(Q[head], Q[head+])) head++;
d[i][j] = DP(Q[head], i);
while(head + < tail && DY(Q[tail-], i) * DX(Q[tail-], Q[tail-]) <= DY(Q[tail-], Q[tail-]) * DX(Q[tail-], i)) tail--;
Q[tail++] = i;
}
} printf("%d\n", d[n][m]);
} return ;
}

代码君

贴一个四边形不等式优化的代码对比一下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int INF = 0x3f3f3f3f; int n, m;
int a[maxn], sum[maxn], cost[maxn];
int d[maxn][maxn], s[maxn][maxn]; int inline w(int k, int j)
{
return cost[j] - cost[k-] - sum[k-] * (sum[j] - sum[k-]);
} int main()
{
while(scanf("%d%d", &n, &m) == && n)
{
m++; for(int i = ; i <= n; i++) scanf("%d", a + i);
for(int i = ; i <= n; i++) sum[i] = sum[i - ] + a[i];
for(int i = ; i <= n; i++) cost[i] = cost[i-] + sum[i-] * a[i]; memset(d, , sizeof(d));
for(int i = ; i <= m; i++)
for(int j = i + ; j <= n; j++) d[i][j] = INF; for(int i = ; i <= n; i++) { d[][i] = cost[i]; s[][i] = ; }
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 tmp = d[i-][k] + w(k+, j);
if(tmp < d[i][j])
{ d[i][j] = tmp; s[i][j] = k; }
}
}
} printf("%d\n", d[m][n]);
} return ;
}

代码君

最新文章

  1. HTML5+CSS3实现图片可倾斜摆放的动画相册效果
  2. mysql apache php install
  3. MySQL备份学习
  4. 【Python自动化运维之路Day9】Socket
  5. Pop - Facebook 开源 iOS &amp; OS X 动画库
  6. C#脚本引擎 CS-Script 之(一)——初识
  7. [bzoj 2431][HAOI2009]逆序对数列(递推+连续和优化)
  8. eclipse中本地项目怎么和svn中的项目关联?
  9. hdoj 2829 Lawrence 四边形不等式优化dp
  10. gitHub添加公钥
  11. 搭建集群必备:windows如何使用Xshell远程连接(SSH)Linux
  12. C++引用作为函数的参数
  13. MapReduce计数器
  14. 开发板怎样开启telnet服务
  15. Linux下smi/mdio总线驱动
  16. CSS层级关系
  17. &lt;ul&gt;标签设计简单导航栏
  18. .NET、PHP、MySql、JS中的时间戳你每次是手写还是复制?这篇文章让你一次性搞懂
  19. git连接不上远程仓库---visualstudio提交代码报错:no upstream configured for branch &#39;master&#39;
  20. zabbix系列~mysql进行监控

热门文章

  1. python+selenium 页面中存在选项卡时,获取页面内容的小技巧
  2. Java中的if-else语句——通过示例学习Java编程(7)
  3. AJPFX关于单例设计模式
  4. Android学习总结(十六) ———— MediaPlayer播放音频与视频
  5. HDU 1729 Stone Game 石头游戏 (Nim, sg函数)
  6. Django添加tinyMCE编辑器
  7. C#入门(3)
  8. UVA 427 The Tower of Babylon 巴比伦塔(dp)
  9. ios push Payload
  10. R文件报错的原因