斜率优化DP:DP的一种优化形式,主要用于优化如下形式的DP
f[i]=f[j]+x[i]*x[j]+...
学习可以参考下面的博客:
https://www.cnblogs.com/Xing-Ling/p/11210179.html
https://blog.csdn.net/xiang_6/article/details/81450647
我的做法结合了这两种方案。
首先,用代数法求出进行状态更新的条件。
然后,判断上凸还是下凸。
在下一步,求出斜率,用于把起始且并不优的状态淘汰。
最后,就可以写代码了
主要题目:
loj10188装箱游戏
1 #include<bits/stdc++.h> 2 #define rll register long long 3 using namespace std; 4 const int maxn=5e7+10; 5 typedef long long ll; 6 ll sum[maxn],f[maxn],q[maxn]; 7 ll n,l,h=1,t=0; 8 9 inline ll min(rll a,rll b){return a<b?a:b;} 10 inline ll X(rll i){return sum[i]+i;} 11 inline ll Y(rll i){return f[i]+(sum[i]+i+1+l)*(sum[i]+i+1+l);} 12 inline long double xl(rll a,rll b){return (long double)(Y(b)-Y(a))/(X(b)-X(a));} 13 14 int main() 15 { 16 scanf("%lld%lld",&n,&l); 17 for(ll i=1;i<=n;++i) 18 { 19 scanf("%lld",sum+i); 20 sum[i]+=sum[i-1]; 21 } 22 q[++t]=0; 23 for(ll i=1;i<=n;++i) 24 { 25 while(h<t && xl(q[h],q[h+1])<=2*(sum[i]+i))++h; 26 int j=q[h]; 27 f[i]=f[j]+(sum[i]-sum[j]+i-j-1-l)*(sum[i]-sum[j]+i-j-1-l); 28 while(h<t && xl(q[t],i)<=xl(q[t-1],q[t]))t--; 29 q[++t]=i; 30 } 31 cout<<f[n]; 32 return 0; 33 }
loj10189仓库建设
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 10; 5 ll n; 6 ll x[maxn], sum[maxn], s[maxn], c[maxn], f[maxn]; 7 ll tail, head, q[maxn]; 8 inline ll X(ll a) { return sum[a]; } 9 inline ll Y(ll a) { return f[a] + s[a]; } 10 inline long double xl(ll a, ll b) { return (long double)(Y(b) - Y(a)) / (X(b) - X(a)); } 11 12 int main() { 13 scanf("%lld", &n); 14 for (ll p, i = 1; i <= n; ++i) { 15 scanf("%lld%lld%lld", x + i, &p, c + i); 16 sum[i] = sum[i - 1] + p; 17 s[i] = s[i - 1] + p * x[i]; 18 } 19 tail = 0, head = 1; 20 q[++tail] = 0; 21 for (ll i = 1; i <= n; ++i) { 22 while (tail > head && xl(q[head], q[head + 1]) <= x[i]) ++head; 23 int j = q[head]; 24 f[i] = f[j] + x[i] * (sum[i] - sum[j]) - s[i] + s[j] + c[i]; 25 while (tail > head && xl(q[tail], i) <= xl(q[tail - 1], q[tail])) --tail; 26 q[++tail] = i; 27 } 28 cout << f[n]; 29 return 0; 30 }
loj10190特别行动队
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e6 + 10; 4 typedef long long ll; 5 ll q[maxn], h = 1, t = 0; 6 ll n, a, b, c, s[maxn], f[maxn]; 7 inline ll X(ll i) { return s[i]; } 8 inline ll Y(ll i) { return f[i] + a * s[i] * s[i] - b * s[i]; } 9 inline long double xl(ll a, ll b) { return (long double)(Y(b) - Y(a)) / (X(b) - X(a)); } 10 int main() { 11 scanf("%lld%lld%lld%lld", &n, &a, &b, &c); 12 for (int i = 1; i <= n; ++i) { 13 scanf("%lld", s + i); 14 s[i] += s[i - 1]; 15 } 16 q[++t] = 0; 17 for (int i = 1; i <= n; ++i) { 18 while (t > h && xl(q[h], q[h + 1]) >= 2 * a * s[i]) ++h; 19 int j = q[h]; 20 f[i] = f[j] + a * (s[i] - s[j]) * (s[i] - s[j]) + b * (s[i] - s[j]) + c; 21 while (t > h && xl(q[t - 1], q[t]) <= xl(q[t], i)) --t; 22 q[++t] = i; 23 } 24 cout << f[n]; 25 return 0; 26 }
loj10191打印文章
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 5e5 + 10; 5 ll n, m; 6 ll s[maxn], f[maxn]; 7 ll h, t, q[maxn]; 8 inline ll X(ll i) { return s[i]; } 9 inline ll Y(ll i) { return f[i] + s[i] * s[i]; } 10 // inline long double xl(ll a,ll b){return (long double)(Y(b)-Y(a))/(X(b)-X(a));} 11 int main() { 12 while (scanf("%lld%lld", &n, &m) == 2) { 13 memset(s, 0, sizeof s); 14 memset(f, 0, sizeof f); 15 memset(q, 0, sizeof q); 16 h = 1, t = 0; 17 for (int i = 1; i <= n; ++i) { 18 scanf("%lld", s + i); 19 s[i] += s[i - 1]; 20 } 21 q[++t] = 0; 22 for (int i = 1; i <= n; ++i) { 23 while (h < t && Y(q[h + 1]) - Y(q[h]) <= 2 * s[i] * (X(q[h + 1]) - X(q[h]))) ++h; 24 ll j = q[h]; 25 f[i] = f[j] + (s[i] - s[j]) * (s[i] - s[j]) + m; 26 while (h < t && 27 (Y(q[t]) - Y(q[t - 1])) * (X(i) - X(q[t])) >= (Y(i) - Y(q[t])) * (X(q[t]) - X(q[t - 1]))) 28 --t; 29 q[++t] = i; 30 } 31 printf("%lld ", f[n]); 32 } 33 return 0; 34 }
loj10192锯木厂选址
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2e5 + 10; 4 typedef long long ll; 5 ll n, dis[maxn], w[maxn], sw[maxn], swd[maxn], f[maxn][2]; 6 ll h = 1, t, q[maxn]; 7 8 inline ll x(ll i) { return sw[i]; } 9 inline ll y(ll i) { return f[i][0] + swd[i]; } 10 11 int main() { 12 scanf("%lld", &n); 13 for (ll d, i = 1; i <= n; ++i) { 14 scanf("%lld%lld", w + i, &d); 15 dis[i + 1] = dis[i] + d; 16 sw[i] = sw[i - 1] + w[i]; 17 swd[i] = swd[i - 1] + w[i] * dis[i]; 18 } 19 sw[n + 1] = sw[n]; 20 swd[n + 1] = swd[n]; 21 for (ll i = 2; i <= n; ++i) f[i][0] = dis[i] * sw[i] - swd[i]; 22 q[++t] = 1; 23 for (ll i = 2; i <= n; ++i) { 24 while (h < t && y(q[h + 1]) - y(q[h]) <= dis[i] * (x(q[h + 1]) - x(q[h]))) ++h; 25 ll j = q[h]; 26 f[i][1] = f[j][0] + dis[i] * (sw[i] - sw[j]) - (swd[i] - swd[j]); 27 while (h < t && 28 (y(q[t]) - y(q[t - 1])) * (x(i) - x(q[t])) >= (y(i) - y(q[t])) * (x(q[t]) - x(q[t - 1]))) 29 --t; 30 q[++t] = i; 31 } 32 ll ans = (ll)1 * 100000000 * 100000000; 33 for (int i = 1; i <= n; ++i) 34 if (ans > f[i][1] + dis[n + 1] * (sw[n + 1] - sw[i]) - (swd[n + 1] - swd[i])) 35 ans = f[i][1] + dis[n + 1] * (sw[n + 1] - sw[i]) - (swd[n + 1] - swd[i]); 36 cout << ans; 37 38 return 0; 39 }
loj10184任务安排1
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 5e3 + 10; 5 ll n, s; 6 ll f[maxn], sc[maxn], st[maxn]; 7 8 int main() { 9 scanf("%lld%lld", &n, &s); 10 for (int i = 1; i <= n; ++i) { 11 scanf("%lld%lld", st + i, sc + i); 12 st[i] += st[i - 1]; 13 sc[i] += sc[i - 1]; 14 } 15 for (int i = n; i > 0; --i) { 16 f[i] = (st[n] + s) * (sc[n] - sc[i - 1]); 17 for (int j = i + 1; j <= n; ++j) { 18 if (f[i] > f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s) 19 f[i] = f[j] + st[j - 1] * (sc[j - 1] - sc[i - 1]) + (sc[n] - sc[i - 1]) * s; 20 } 21 } 22 cout << f[1]; 23 return 0; 24 }
loj10185任务安排2
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e4+10; 5 int n,s; 6 int f[maxn],sc[maxn],smt[maxn]; 7 int q[maxn],l,r; 8 ll y(int a) 9 { 10 return f[a]+sc[a]*smt[a]; 11 } 12 long double get_xl(int a,int b) 13 { 14 return (long double)(y(b)-y(a))/(smt[b]-smt[a]); 15 } 16 int main() 17 { 18 scanf("%d%d",&n,&s); 19 for(int t,c,i=1;i<=n;++i) 20 { 21 scanf("%d%d",&smt[i],&sc[i]); 22 smt[i]+=smt[i-1]; 23 sc[i]+=sc[i-1]; 24 } 25 for(int i=n;i>=0;--i) 26 { 27 while(l<r&&get_xl(q[l],q[l+1])>=sc[i])++l; 28 f[i]=f[q[l]]+(sc[q[l]]-sc[i])*smt[q[l]]+(sc[n]-sc[i])*s; 29 while(l<r&&get_xl(q[r-1],q[r])<=get_xl(q[r],i))--r; 30 q[++r]=i; 31 } 32 cout<<f[0]<<endl; 33 return 0; 34 }