|
板凳
楼主 |
发表于 2021-10-14 14:51:31
|
只看该作者
(2015年北大自招夏令营)
考虑最后出栈的是i,则1至i-1在i入栈前就已经弹出,与i+1至n的顺序没有关系,并且i+1至n的惩罚值只跟他们的顺序与∑tj(1<=j<i)有关即可以将[1,n]的计算转化为两个子问题[1,i-1]和[i+1,n]。
令f(l,r)表示[l,r]的最小惩罚值。
f(l,r)= min(f(l,m-1)+f(m+1,r)+(stm-1-stl-1)*(sdr-sdm)+(str-stl-1)*dm) (l<=m<=r,其中st为时间前缀和,sd为惩罚前缀和)
时间复杂度O(N3)。空间复杂度O(N2)。
- #include<iostream>
- #include<cstdio>
- #define FOR(i,a,b) for(int i=a;i<=b;i++)
- using namespace std;
- typedef long long ll;
- const int N=550;
- const ll INF=1e13;
- int n;
- ll t[N],d[N],st[N],sd[N],f[N][N];
- int main()
- {
- freopen("product.in","r",stdin);
- freopen("product.out","w",stdout);
- scanf("%d",&n);
- FOR(i,1,n) scanf("%lld%lld",&t[i],&d[i]);
- FOR(i,1,n) st[i]=st[i-1]+t[i],sd[i]=sd[i-1]+d[i];
- FOR(i,1,n) f[i][i]=t[i]*d[i];
- FOR(L,2,n)
- {
- FOR(i,1,n-L+1)
- {
- int j=i+L-1;
- f[i][j]=INF;
- FOR(k,i,j-1)
- f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+(st[k]-st[i-1])*(sd[j]-sd[k]));
- f[i][j]=min(f[i][j],f[i+1][j]+d[i]*(st[j]-st[i-1]));
- //cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
- }
- }
- printf("%lld",f[1][n]);
- }
复制代码
|
|