BZOJ 1597: [Usaco2008 Mar]土地购买
做法:斜率优化DP
斜率优化DP:Link
预处理:sort处理可合并土地,得到a[]严格上升,b[]严格下降的序列
朴素DP方程:F[i]=min f[j]+a[i]*b[j+1](0<j<i)
朴素DP Code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ll long long 5 using namespace std; 6 inline int read() 7 { 8 register int f=1,k=0;register char c=getchar(); 9 while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 10 while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar(); 11 return k*f; 12 } 13 const int maxn=50100; 14 struct qaq{ 15 ll a,b; 16 }x[maxn],y[maxn]; 17 ll f[maxn]; 18 inline bool cmp(const qaq&a,const qaq&b){return a.a<b.a||(a.a==b.a&&a.b<b.b);} 19 int main() 20 { 21 memset(f,0x7f,sizeof(f)); 22 register int i,n=read(),cur=1; 23 for (i=1;i<=n;i++) 24 x[i].a=read(),x[i].b=read(); 25 sort(x+1,x+1+n,cmp); 26 y[1]=x[1]; 27 for (register int i=2;i<=n;i++) 28 { 29 while (x[i].b>=y[cur].b&&cur>0)cur--; 30 y[++cur]=x[i]; 31 } 32 f[1]=y[1].a*y[1].b; 33 for (register int i=1;i<=cur;i++) 34 for (register int j=1;j<i;j++) 35 f[i]=min(f[i],f[j]+y[i].a*y[j+1].b); 36 printf("%lld\n",f[cur]); 37 }
斜率优化DP:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long using namespace std; inline int read() { register int f=1,k=0;register char c=getchar(); while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } const int maxn=50100; struct qaq{ll a,b;}x[maxn],y[maxn]; ll f[maxn],q[maxn]; inline int d(int a,int b){return (f[a]-f[b])/(y[b+1].b-y[a+1].b);} inline bool cmp(const qaq&a,const qaq&b){return a.a<b.a||(a.a==b.a&&a.b<b.b);} int main() { register int i,n=read(),cur=1,head=0,tail=1; for (i=1;i<=n;i++)x[i].a=read(),x[i].b=read(); sort(x+1,x+1+n,cmp); y[1]=x[1]; for (register int i=2;i<=n;y[++cur]=x[i++])while (x[i].b>=y[cur].b&&cur>0)cur--; for (register int i=1;i<=cur;i++) { while (tail-head>1&&d(q[head],q[head+1])<y[i].a)head++; f[i]=f[q[head]]+1ll*y[i].a*y[q[head]+1].b; while (tail-head>1&&d(q[tail-1],q[tail-2])>d(q[tail-1],i))tail--; q[tail++]=i; } printf("%lld\n",f[cur]); }