【HNOI2008】【斜率优化DP】玩具装箱
2013-04-03 10:01
253 查看
很直观的一维DP
状态:f[i]表示将前i个玩具打包的最小费用。
朴素方程:f[i] = min{f[j] + (w[j+1][i]
- L) ^ 2}
(w[j+1][i] =∑
Ck + i - (j + 1),j < i,k
∈[j+1,i])
但是直接朴素会TLE,所以我们考虑将方程变形,挖掘方程的性质。
令sum[i]=
∑Ck k∈
[1,i]
->
f[i] = min{
f[j] + (sum[i] - sum[j] + i - j - 1
- L) ^ 2 }
令s[i]
= sum[i] + i
->
f[i] = min{ f[j] + (s[i] - s[j] -
L - 1) ^ 2}
令m
= s[i] - l - 1
->
f[i] = min{ f[j] + (m - s[j]) ^ 2 }
->
f[i] = min{ f[j] + m ^ 2
- 2 * m * s[j] + s[j] ^ 2 }
考虑∀决策k,k
< i且决策k比决策j更优
->f[k]
- 2 * m * s[k] + s[k] ^ 2 + m ^ 2 < f[j] - 2 * m * s[j] + s[j] ^ 2 + m ^ 2
->
f[k] - 2 * m * s[k] + s[k] ^ 2 < f[j] - 2 * m
* s[j] + s[j] ^ 2
->
(f[k] + s[k] ^ 2) - (f[j] + s[j] ^ 2)/
(s[k] - s[j]) < 2 * m
这样我们可以令x
= s[i],y = f[j] + s[j] ^ 2
则可以将每个决策看作两个点,只要满足上述条件则决策更优,使用一个队列来维护最优决策就可以了。
代码:
状态:f[i]表示将前i个玩具打包的最小费用。
朴素方程:f[i] = min{f[j] + (w[j+1][i]
- L) ^ 2}
(w[j+1][i] =∑
Ck + i - (j + 1),j < i,k
∈[j+1,i])
但是直接朴素会TLE,所以我们考虑将方程变形,挖掘方程的性质。
令sum[i]=
∑Ck k∈
[1,i]
->
f[i] = min{
f[j] + (sum[i] - sum[j] + i - j - 1
- L) ^ 2 }
令s[i]
= sum[i] + i
->
f[i] = min{ f[j] + (s[i] - s[j] -
L - 1) ^ 2}
令m
= s[i] - l - 1
->
f[i] = min{ f[j] + (m - s[j]) ^ 2 }
->
f[i] = min{ f[j] + m ^ 2
- 2 * m * s[j] + s[j] ^ 2 }
考虑∀决策k,k
< i且决策k比决策j更优
->f[k]
- 2 * m * s[k] + s[k] ^ 2 + m ^ 2 < f[j] - 2 * m * s[j] + s[j] ^ 2 + m ^ 2
->
f[k] - 2 * m * s[k] + s[k] ^ 2 < f[j] - 2 * m
* s[j] + s[j] ^ 2
->
(f[k] + s[k] ^ 2) - (f[j] + s[j] ^ 2)/
(s[k] - s[j]) < 2 * m
这样我们可以令x
= s[i],y = f[j] + s[j] ^ 2
则可以将每个决策看作两个点,只要满足上述条件则决策更优,使用一个队列来维护最优决策就可以了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 50000 + 10; int deq[maxn]; long long c[maxn],S[maxn],f[maxn]; int n,l; void init() { freopen("bzoj1010.in","r",stdin); freopen("bzoj1010.out","w",stdout); } inline double slope(int i,int j) { return (double)((f[i] + S[i] * S[i] - f[j] - S[j] * S[j]) / (S[i] - S[j])); } void readdata() { memset(c,0,sizeof(c)); memset(S,0,sizeof(S)); scanf("%d%d",&n,&l); for(int i = 1;i <= n;i++) { scanf("%lld",&c[i]); c[i] += c[i-1];S[i] = c[i] + i; } } void solve() { memset(f,0,sizeof(f)); int s = 0,e = 0; for(int i = 1;i <= n;i++) { long long m = S[i] - l - 1; while(s < e && slope(deq[s+1],deq[s]) <= 2 * m)++s; int j = deq[s]; f[i] = f[j] + (m - S[j]) * (m - S[j]); while(s < e && slope(deq[e],deq[e-1]) >= slope(i,deq[e]))--e; deq[++e] = i; } printf("%lld\n",f ); } int main() { init(); readdata(); solve(); return 0; }
相关文章推荐
- [hnoi2008]玩具装箱题解(斜率优化的dp)
- 【斜率优化DP】BZOJ1010 [HNOI2008]玩具装箱toy
- Bzoj 1010[HNOI2008]玩具装箱toy【斜率优化Dp入门】
- 1010: [HNOI2008]玩具装箱toy DP+斜率优化+决策单调性
- BZOJ 斜率优化dp 1010: [HNOI2008]玩具装箱toy
- BZOJ1010: [HNOI2008]玩具装箱toy 斜率优化DP
- BZOJ 1010: [HNOI2008]玩具装箱toy(dp+斜率优化)
- 【bzoj 1010】[HNOI2008] 玩具装箱toy(斜率优化dp)
- [HNOI2008]玩具装箱toy(dp+斜率优化)
- BZOJ 1010 [HNOI2008]玩具装箱 (斜率优化DP)
- BZOJ 1010 [HNOI2008]玩具装箱toy(斜率优化dp)
- 【BZOJ】1010: [HNOI2008]玩具装箱toy(dp+斜率优化)
- bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)
- bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
- 【OI做题记录】【BZOJ】【斜率优化DP】【HNOI2008】玩具装箱
- BZOJ 1010 [HNOI2008]玩具装箱 (斜率优化DP)
- BZOJ1010 [HNOI2008]玩具装箱toy(斜率优化dp)
- 【HNOI2008】【BZOJ1010】玩具装箱(斜率优化DP)
- [bzoj1010][HNOI2008] 玩具装箱toy DP斜率优化
- BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP