B - Lawrence

HDU - 2829

这个题目我觉得很难,难在这个dp方程不会写。

看了网上的题解,看了很久才理解这个dp转移方程

dp[i][j] 表示前面1~j 位并且以 j 结尾分成了 i 段的最小权值和

再定义一个数组 w[a,b] 表示 a到b 的权值和,注意这个不是前缀和,而是题目给的那种权值和

比如 a 到 b  是4 5 1 2 Its Strategic Value is 4*5 + 4*1 + 4*2 + 5*1 + 5*2 + 1*2 = 49.

w[a,b]=49

然后再定义一个val[i] ==w[1,i] 意思就是前缀权值和 val[i]=val[i-1]+sum[i-1]*a[i]

因为这个w[a,b]不好直接推出来,但是可以借助前缀来推。

求w[a+1,b]=val[b]-val[a]-(sum[b]-sum[a])*sum[a]

然后这个dp方程就可以推出来了

dp[i,j]=min(dp[i-1,k]+w[k+1,j])

但是这个直接暴力n^3肯定是过不了的,所以需要优化,这个式子是不是和之前推过的斜率优化的式子很像。

如果在dp[i-1,k]之外还存在k这个值,一般都是可以用斜率优化来优化这个dp的。

然后就可以推出和之前一样的式子(之前指的是D - Pearls HDU - 1300 斜率dp+二分  斜率dp A - Print Article HDU - 3507

令 F[h]=dp[i-1][h]-val[h]+sum[h]*sum[h]

所以G[h,k]=(F[h]-F[k)/(sum[h]-sum[k])<sum[j]

然后就是一样的推导了

如果存在 i>j>k G[i,j]>G[j,k]

1 G[i,j]>Gj,k]>sum[t]  k 比 j 优 ,j 比 i 优

2 G[i,j]>sum[t]>G[j,k] 那么 j 比 i 优,j 比 k 优

3 sum[t]>G[i,j]>G[j,k] i 比 j 优 j 比k 优

如果是 i > j > k G[i,j]<G[j,k]

1 G[i,j]<G[j,k]<sum[t] j 比 k 优 i 比 j 优

2. G[i,j]<sum[t]<G[j,k] i 比 j 优 k 比 j 优

3 sum[t]<G[i,j]<G[j,k]  j 比 i 优 k 比 j 优

这种情况之下,j 肯定是要被排除的,所以如果从后面插入 i 的时候 前面的 j 如果和它构成的斜率小于这个数和之前的那个数构成的斜率,

那么这个 j 肯定是不要的。

因为这个前缀和sum是单调的,所以可以用单调队列优化这个dp。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <iostream>
#include <string>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
ll dp[][], sum[], val[], a[];
int que[maxn]; ll up(int i,int j,int k)
{
return dp[i - ][j] - val[j] + sum[j] * sum[j] - (dp[i - ][k] - val[k] + sum[k] * sum[k]);
} ll down(int j,int k)
{
return sum[j] - sum[k];
} ll DP(int i,int j,int k)
{
return dp[i - ][k] + val[j] - val[k] - (sum[j] - sum[k])*sum[k];
} int main()
{
int n, m;
while (scanf("%d%d", &n, &m) && (n + m)) {
sum[] = ;
val[] = ;
for (int i = ; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i - ] + a[i];
val[i] = val[i - ] + sum[i - ] * a[i];
}
for (int i = ; i <= n; i++) dp[][i] = val[i];//注意这个题目的初始化
for (int i = ; i <= m + ; i++) {
int head = , tail = ;//注意dp[i,j]的定义是以j结尾分成了i块的最小价值
que[tail++] = i - ;//因为下一段要分成i块,所以前面最少也占了i-1个数,而后面又有可能全部分成一块,注意这种情况不要漏掉
for (int j = i; j <= n; j++) {//注意这个j必须要从i开始
while (head + < tail&&up(i, que[head + ], que[head]) <= sum[j] * down(que[head + ], que[head])) head++;
dp[i][j] = DP(i, j, que[head]);
while (head + < tail&&up(i, j, que[tail - ])*down(que[tail - ], que[tail - ]) <= up(i, que[tail - ], que[tail - ])*down(j, que[tail - ])) tail--;
que[tail++] = j;
}
}
printf("%lld\n", dp[m + ][n]);
}
return ;
}

B - Lawrence HDU - 2829 斜率dp dp转移方程不好写的更多相关文章

  1. HDU 2829 斜率优化DP Lawrence

    题意:n个数之间放m个障碍,分隔成m+1段.对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小. 设: d(i, j)表示前i个数之间放j个炸弹能得到的最小值 sum(i)为前缀和,co ...

  2. hdu 2829 斜率DP

    思路:dp[i][x]=dp[j][x-1]+val[i]-val[j]-sum[j]*sum[i]+sum[j]*sum[j]; 其中val[i]表示1~~i是一段的权值. 然后就是普通斜率dp做法 ...

  3. HDU 4258 斜率优化dp

    Covered Walkway Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. hdu 3045 斜率优化DP

    思路:dp[i]=dp[j]+sum[i]-sum[j]-(i-j)*num[j+1]; 然后就是比较斜率. 注意的时这里j+t<=i: #include<iostream> #in ...

  5. hdu 3669(斜率优化DP)

    Cross the Wall Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) ...

  6. Print Article HDU - 3507 -斜率优化DP

    思路 : 1,用一个单调队列来维护解集. 2,假设队列中从头到尾已经有元素a b c.那么当d要入队的时候,我们维护队列的下凸性质, 即如果g[d,c]<g[c,b],那么就将c点删除.直到找到 ...

  7. HDU 3507 斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  8. HDU 3507斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  9. HDU 3507 斜率优化 DP Print Article

    在kuangbin巨巨博客上学的. #include <iostream> #include <cstdio> #include <cstring> #includ ...

随机推荐

  1. selemiun 下拉菜单、复选框、弹框定位识别

    一.下拉菜单识别 对下拉框的操作,主要是通过Select 类里面的方法来实现的,所以需要new 一个Select 对象(org.openqa.selenium.support.ui.Select)来进 ...

  2. HTML+CSS教程(二)frameset框架和iframe内嵌

    一.框架 (frameset)1.用<frameset></frameset>代替了<body></body>2.rows设置行的占页面的百分比:col ...

  3. 如何用Github钩子做自动部署

    最近机缘巧合的购置了域名和服务器,不用实在是浪费,再加上一直没有属于自己的个人网站,所以打算用hexo在服务器上玩一下,这样也就不用再纠结用Github pages还是Gitee pages了.当然, ...

  4. 解决QQ可以登录但是网页打不卡 ,提示代理服务器拒绝连接 的问题。

  5. Handler 机制(一)—— Handler的实现流程

    由于Android采用的是单线程模式,开发者无法在子线程中更新 UI,所以系统给我提供了 Handler 这个类来实现 UI 更新问题.本贴主要说明 Handler 的工作流程. 1. Handler ...

  6. 47000名开发者每月产生30000个漏洞 微软是如何用AI排查的

    目前微软共有 47000 多名开发人员,每月会产生将近 30000 个漏洞,而这些漏洞会存储在 100 多个 AzureDevOps 和 GitHub 仓库中,以便于在被黑客利用之前快速发现关键的漏洞 ...

  7. 标准SQL语句大全【持续更新】(navicat12版亲测有效)

    提示:用ctrl+F快速查找相关指令哦 -- 创建数据库 create database test_sql; -- 修改数据库名称(只有 sysadmin 和 dbcreator 固定服务器角色的成员 ...

  8. Ansible 配置文件详解

    # config file for ansible -- http://ansible.com/ # ============================================== #  ...

  9. KafkaConsumer assign VS subscribe

    背景 在kafka中,正常情况下,同一个group.id下的不同消费者不会消费同样的partition,也即某个partition在任何时刻都只能被具有相同group.id的consumer中的一个消 ...

  10. mybatis源码学习(四):动态SQL的解析

    之前的一片文章中我们已经了解了MappedStatement中有一个SqlSource字段,而SqlSource又有一个getBoundSql方法来获得BoundSql对象.而BoundSql中的sq ...