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:

 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 }
View Code

 斜率优化DP:

#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]); 
}
View Code

 

posted @ 2017-10-26 10:13  Michael_Zhuang  阅读(158)  评论(0编辑  收藏  举报