信息学奥赛一本通 1612:特别行动队 | 洛谷 P3628 [APIO2010] 特别行动队
【题目链接】
ybt 1612:特别行动队
洛谷 P3628 [APIO2010] 特别行动队
【题目考点】
1. 动态规划:斜率优化动规
斜率优化的具体原理、和代码细节参考模板题:
信息学奥赛一本通 1607:【 例 2】任务安排 2 | 洛谷 P10979 任务安排 2
【解题思路】
给定整数序列 x x x,每个整数是一个元素,每个行动队是该序列的一个子段。根据计算可以得到该行动队的战斗力,将战斗力叫做费用
状态定义
- 阶段:前i个元素
- 决策:是否将第i加入子段
- 策略:子段划分的方案
- 策略集合:前i个元素的所有子段划分方案。
- 条件:费用最大
- 统计量:费用
状态定义 d p i dp_i dpi:前i个元素的所有子段划分方案中,费用最大的方案的费用。
初始状态 d p 0 = 0 dp_0=0 dp0=0
状态转移方程
- 策略集合:前 i i i个元素的所有子段划分方案。
- 分割策略集合:根据最后一个子段的起始位置分割策略集合。
记最后一个子段的起始位置为 j + 1 j+1 j+1, j j j最小为 0 0 0,最大为 i − 1 i-1 i−1,因此 0 ≤ j ≤ i − 1 0\le j \le i-1 0≤j≤i−1
前 j j j个元素进制子段划分得到的最大费用为 d p j dp_{j} dpj。
第 j + 1 j+1 j+1到第 i i i元素贡献的费用为: x = ∑ k = j + 1 i x k x=\sum_{k=j+1}^ix_k x=∑k=j+1ixk,而后费用为 a x 2 + b x + c ax^2+bx+c ax2+bx+c
设 x x x序列的前缀和为 s x sx sx,则 x = s x i − s x j x=sx_i-sx_{j} x=sxi−sxj,所需费用为 a ( s x i − s x j ) 2 + b ( s x i − s x j ) + c a(sx_i-sx_j)^2+b(sx_i-sx_j)+c a(sxi−sxj)2+b(sxi−sxj)+c
对于 j j j的所有可能取值,取费用的最小值。
状态转移方程为:
d p i = m i n { d p j + a ( s x i − s x j ) 2 + b ( s x i − s x j ) + c } , 0 ≤ j ≤ i − 1 dp_i=min\{dp_j+a(sx_i-sx_j)^2+b(sx_i-sx_j)+c\},0\le j \le i-1 dpi=min{dpj+a(sxi−sxj)2+b(sxi−sxj)+c},0≤j≤i−1
进行斜率优化动规,去掉min,将与 j j j相关的表达式视为变量
− d p j = − d p i + a ( s x i 2 − 2 s x i ⋅ s x j + s x j 2 ) + b ⋅ s x i − b ⋅ s x j + c -dp_j=-dp_i+a(sx_i^2-2sx_i\cdot sx_j+sx_j^2)+b\cdot sx_i-b\cdot sx_j+c −dpj=−dpi+a(sxi2−2sxi⋅sxj+sxj2)+b⋅sxi−b⋅sxj+c
− d p j − a ⋅ s x j 2 + b ⋅ s x j = − 2 a ⋅ s x i ⋅ s x j − d p i + a ⋅ s x i 2 + b ⋅ s x i + c -dp_j-a\cdot sx_j^2+b\cdot sx_j = -2a\cdot sx_i\cdot sx_j-dp_i+a\cdot sx_i^2+b\cdot sx_i+c −dpj−a⋅sxj2+b⋅sxj=−2a⋅sxi⋅sxj−dpi+a⋅sxi2+b⋅sxi+c
解法1: 斜率 k k k随着 i i i的增大单调递增
(建议将斜率 k k k设计为随着 i i i的增大单调递增,这样方便写固定的模板代码,减少出错。)
设:
y = − d p j − a ⋅ s x j 2 + b ⋅ s x j y=-dp_j-a\cdot sx_j^2+b\cdot sx_j y=−dpj−a⋅sxj2+b⋅sxj,
x = s x j x=sx_j x=sxj
k = − 2 a ⋅ s x i k=-2a\cdot sx_i k=−2a⋅sxi
b = − d p i + a ⋅ s x i 2 + b ⋅ s x i + c b=-dp_i+a\cdot sx_i^2+b\cdot sx_i+c b=−dpi+a⋅sxi2+b⋅sxi+c
则该方程为 y = k x + b y=kx+b y=kx+b,直线斜率固定,看过哪个决策点 ( s x j , − d p j − a ⋅ s x j 2 + b ⋅ s x j ) (sx_j,-dp_j-a\cdot sx_j^2+b\cdot sx_j) (sxj,−dpj−a⋅sxj2+b⋅sxj)时直线截距最小,此时 d p i dp_i dpi最大。
由于已知 a < 0 a<0 a<0,直线斜率 k = − 2 a ⋅ s x i k=-2a\cdot sx_i k=−2a⋅sxi随着 i i i的增大而增大。
使用单调队列 q q q维护决策点集的下凸壳, q l q_l ql是队头, q r q_r qr是队尾。单调队列中相邻两决策点连线的斜率是单调递增的。
K ( a , b ) K(a,b) K(a,b)是 a a a、 b b b两个决策点连线的斜率。
每次循环新加入决策点为 j = i − 1 j=i-1 j=i−1,只要 K ( q r , i − 1 ) ≤ K ( q r − 1 , q r ) K(q_r,i-1)\le K(q_{r-1}, q_r) K(qr,i−1)≤K(qr−1,qr),则队尾出队,当 K ( q r , i − 1 ) > K ( q r − 1 , q r ) K(q_r,i-1)> K(q_{r-1}, q_r) K(qr,i−1)>K(qr−1,qr)时将 i − 1 i-1 i−1队尾入队。
只要 K ( q l , q l + 1 ) ≤ − 2 a ⋅ s x i K(q_l,q_{l+1})\le -2a\cdot sx_i K(ql,ql+1)≤−2a⋅sxi,则队头出队。
队头 q l q_l ql就是最优决策点,令 j = q l j=q_l j=ql,代入状态转移方程,求出 d p i dp_i dpi。
最终结果为 d p n dp_n dpn
解法2: 斜率 k k k随着 i i i的增大单调递减
− d p j − a ⋅ s x j 2 + b ⋅ s x j = − 2 a ⋅ s x i ⋅ s x j − d p i + a ⋅ s x i 2 + b ⋅ s x i + c -dp_j-a\cdot sx_j^2+b\cdot sx_j = -2a\cdot sx_i\cdot sx_j-dp_i+a\cdot sx_i^2+b\cdot sx_i+c −dpj−a⋅sxj2+b⋅sxj=−2a⋅sxi⋅sxj−dpi+a⋅sxi2+b⋅sxi+c
等号两侧乘以 − 1 -1 −1得:
d p j + a ⋅ s x j 2 − b ⋅ s x j = 2 a ⋅ s x i ⋅ s x j + d p i − a ⋅ s x i 2 − b ⋅ s x i − c dp_j+a\cdot sx_j^2-b\cdot sx_j = 2a\cdot sx_i\cdot sx_j+dp_i-a\cdot sx_i^2-b\cdot sx_i-c dpj+a⋅sxj2−b⋅sxj=2a⋅sxi⋅sxj+dpi−a⋅sxi2−b⋅sxi−c
设:
y = d p j + a ⋅ s x j 2 − b ⋅ s x j y=dp_j+a\cdot sx_j^2-b\cdot sx_j y=dpj+a⋅sxj2−b⋅sxj,
x = s x j x=sx_j x=sxj
k = 2 a ⋅ s x i k=2a\cdot sx_i k=2a⋅sxi
b = d p i − a ⋅ s x i 2 − b ⋅ s x i − c b=dp_i-a\cdot sx_i^2-b\cdot sx_i-c b=dpi−a⋅sxi2−b⋅sxi−c
则该方程为 y = k x + b y=kx+b y=kx+b,直线斜率固定,看过哪个决策点 ( s x j , d p j + a ⋅ s x j 2 − b ⋅ s x j ) (sx_j,dp_j+a\cdot sx_j^2-b\cdot sx_j) (sxj,dpj+a⋅sxj2−b⋅sxj)时直线截距最大,此时 d p i dp_i dpi最大。
由于已知 a < 0 a<0 a<0,直线斜率 k = 2 a ⋅ s x i k=2a\cdot sx_i k=2a⋅sxi随着 i i i的增大而减小。
使用单调队列 q q q维护决策点集的上凸壳, q l q_l ql是队头, q r q_r qr是队尾。单调队列中相邻两决策点连线的斜率是单调递减的。
K ( a , b ) K(a,b) K(a,b)是 a a a、 b b b两个决策点连线的斜率。
每次循环新加入决策点为 j = i − 1 j=i-1 j=i−1,只要 K ( q r , i − 1 ) ≥ K ( q r − 1 , q r ) K(q_r,i-1)\ge K(q_{r-1}, q_r) K(qr,i−1)≥K(qr−1,qr),则队尾出队。当 K ( q r , i − 1 ) < K ( q r − 1 , q r ) K(q_r,i-1)< K(q_{r-1}, q_r) K(qr,i−1)<K(qr−1,qr)时将 i − 1 i-1 i−1队尾入队。
只要 K ( q l , q l + 1 ) ≥ 2 a ⋅ s x i K(q_l,q_{l+1})\ge 2a\cdot sx_i K(ql,ql+1)≥2a⋅sxi,则队头出队。
队头 q l q_l ql就是最优决策点,令 j = q l j=q_l j=ql,代入状态转移方程,求出 d p i dp_i dpi。
最终结果为 d p n dp_n dpn
【题解代码】
解法1:斜率 k k k随着 i i i的增大单调递增
#include<bits/stdc++.h>
using namespace std;
#define N 1000005
typedef long long LL;
LL n, a, b, c, x[N], sx[N], dp[N];
int q[N], l = 1, r = 0;
LL X(int j)
{
return sx[j];
}
LL Y(int j)
{
return -dp[j]-a*sx[j]*sx[j]+b*sx[j];
}
LL K(int i)
{
return -2*a*sx[i];
}
bool cmp(LL y1, LL x1, LL y2, LL x2)//y1/x1 <= y2/x2
{
return y1*x2 <= y2*x1;
}
int main()
{
cin >> n >> a >> b >> c;
for(int i = 1; i <= n; ++i)
{
cin >> x[i];
sx[i] = sx[i-1]+x[i];
}
for(int i = 1; i <= n; ++i)
{
while(l < r && cmp(Y(i-1)-Y(q[r]), X(i-1)-X(q[r]), Y(q[r])-Y(q[r-1]), X(q[r])-X(q[r-1])))
r--;
q[++r] = i-1;
while(l < r && cmp(Y(q[l+1])-Y(q[l]), X(q[l+1])-X(q[l]), K(i), 1))
l++;
dp[i] = dp[q[l]]+a*(sx[i]-sx[q[l]])*(sx[i]-sx[q[l]])+b*(sx[i]-sx[q[l]])+c;
}
cout << dp[n];
return 0;
}
解法2:斜率 k k k随着 i i i的增大单调递减
#include<bits/stdc++.h>
using namespace std;
#define N 1000005
typedef long long LL;
LL n, a, b, c, x[N], sx[N], dp[N];
int q[N], l = 1, r = 0;
LL X(int j)
{
return sx[j];
}
LL Y(int j)
{
return dp[j]+a*sx[j]*sx[j]-b*sx[j];
}
LL K(int i)
{
return 2*a*sx[i];
}
bool cmp(LL y1, LL x1, LL y2, LL x2)//y1/x1 >= y2/x2
{
return y1*x2 >= y2*x1;
}
int main()
{
cin >> n >> a >> b >> c;
for(int i = 1; i <= n; ++i)
{
cin >> x[i];
sx[i] = sx[i-1]+x[i];
}
for(int i = 1; i <= n; ++i)
{
while(l < r && cmp(Y(i-1)-Y(q[r]), X(i-1)-X(q[r]), Y(q[r])-Y(q[r-1]), X(q[r])-X(q[r-1])))
r--;
q[++r] = i-1;
while(l < r && cmp(Y(q[l+1])-Y(q[l]), X(q[l+1])-X(q[l]), K(i), 1))
l++;
dp[i] = dp[q[l]]+a*(sx[i]-sx[q[l]])*(sx[i]-sx[q[l]])+b*(sx[i]-sx[q[l]])+c;
}
cout << dp[n];
return 0;
}
更多推荐



所有评论(0)