斜率优化

斜率优化

1.费用提前计算

O(N^2)

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN=5e3+100;
LL f[MAXN],sumt[MAXN],sumc[MAXN];
int N,S;
int main()
{
   scanf("%d%d",&N,&S);
   int t,c;
   for(int i=1;i<=N;++i){
       scanf("%d%d",&t,&c);
       sumt[i]=sumt[i-1]+t;
       sumc[i]=sumc[i-1]+c;
  }
   memset(f,0x3f,sizeof(f));
   f[0]=0;
   for(int i=1;i<=N;++i){
       for(int j=0;j<i;++j){
           f[i]=min(f[i],f[j]+sumt[i]*(sumc[i]-sumc[j])+S*(sumc[N]-sumc[j]));
      }
  }
   printf("%lld\n",f[N]);

   return 0;
}

2.斜率优化

O(N)

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN=3e5+100;
LL f[MAXN],sumt[MAXN],sumc[MAXN],q[MAXN];
int N,S;
int main()
{
   scanf("%d%d",&N,&S);
   int t,c;
   for(int i=1;i<=N;++i){
       scanf("%d%d",&t,&c);
       sumt[i]=sumt[i-1]+t;
       sumc[i]=sumc[i-1]+c;
  }
   memset(f,0x3f,sizeof(f));
   f[0]=0;
   int L=1,R=1;
   q[1]=0;
   for(int i=1;i<=N;++i){
       while(L<R&&(f[q[L+1]]-f[q[L]])<=(S+sumt[i])*(sumc[q[L+1]]-sumc[q[L]])) L++;
       f[i]=f[q[L]]-(S+sumt[i])*sumc[q[L]]+sumt[i]*sumc[i]+S*sumc[N];
       while(L<R&&(f[q[R]]-f[q[R-1]])*(sumc[i]-sumc[q[R]])>=(f[i]-f[q[R]])*(sumc[q[R]]-sumc[q[R-1]])) R--;
       q[++R]=i;
  }
   printf("%lld\n",f[N]);

   return 0;
}

斜率优化,维护整个凸壳,不需要队头删除,但是需要二分查找最优解。

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN=3e5+100;
LL f[MAXN],sumt[MAXN],sumc[MAXN],q[MAXN];
int N,S,L,R;
int b_search(int k)
{
   if(L==R) return q[L];
   int l=L,r=R,mid;
   while(l<r){
       mid=(l+r)>>1;
       if(f[q[mid+1]]-f[q[mid]]<=k*(sumc[q[mid+1]]-sumc[q[mid]])) l=mid+1;
       else r=mid;
  }
   return q[r];
}
int main()
{
   scanf("%d%d",&N,&S);
   int t,c;
   for(int i=1;i<=N;++i){
       scanf("%d%d",&t,&c);
       sumt[i]=sumt[i-1]+t;
       sumc[i]=sumc[i-1]+c;
  }
   memset(f,0x3f,sizeof(f));
   f[0]=0;
   L=1,R=1;
   q[1]=0;
   int p;
   for(int i=1;i<=N;++i){
       p=b_search(sumt[i]+S);
       f[i]=f[p]-(S+sumt[i])*sumc[p]+sumt[i]*sumc[i]+S*sumc[N];
       while(L<R&&(f[q[R]]-f[q[R-1]])*(sumc[i]-sumc[q[R]])>=(f[i]-f[q[R]])*(sumc[q[R]]-sumc[q[R-1]])) R--;
       q[++R]=i;
  }
   printf("%lld\n",f[N]);

   return 0;
}



posted @ 2022-02-26 23:05  fengzlj  阅读(55)  评论(0)    收藏  举报