1 条题解
-
0
方法一:O(n²)动态规划
/* O(n²)的方法: dp[i]:表示前i个任务最小要用多少时间。初始化memset(dp,63,sizeof(dp));dp[0]=0; 状态方程:dp[i]=min( dp[i], dp[j] + st[i]*(sf[i]-sf[j]) + s*(sf[n]-sf[j]) ); (0<=j<=i-1)(最后一组为 j+1、j+2……i) 最后答案:dp[n] */ #include<bits/stdc++.h> using namespace std; const int N=11100; int dp[N],f[N],t[N],st[N],sf[N]; int main() { int n,s;scanf("%d%d",&n,&s); st[0]=0;sf[0]=0; for(int i=1;i<=n;i++) { scanf("%d%d",&t[i],&f[i]); st[i]=st[i-1]+t[i]; sf[i]=sf[i-1]+f[i]; } memset(dp,63,sizeof(dp));dp[0]=0; for(int i=1;i<=n;i++) { for(int j=i-1;j>=0;j--) { dp[i]=min(dp[i],dp[j]+st[i]*(sf[i]-sf[j])+s*(sf[n]-sf[j])); } } printf("%d\n",dp[n]); return 0; }方法二:斜率优化动态规划
/* 也可以用斜率优化。 dp[i]=min(dp[i],dp[j]+st[i]*(sf[i]-sf[j])+s*(sf[n]-sf[j])); dp[i]=dp[j]+st[i]*(sf[i]-sf[j])+s*(sf[n]-sf[j])); dp[i]-st[i]*sf[i]-s*sf[n]= dp[j]-s*sf[j]- st[i]*sf[j] dp[j]-s*sf[j] =st[i]*sf[j] + dp[i]-st[i]*sf[i]-s*sf[n] yj=dp[j]-s*sf[j] xj=sf[j] k=st[i] b=dp[i]-st[i]*sf[i]-s*sf[n] */ #include<bits/stdc++.h> using namespace std; typedef long long LL; const int N=11100; LL dp[N],f[N],t[N],st[N],sf[N],s;int q[N]; double X(int j){ return 1.0*sf[j];} double Y(int j){ return 1.0*(dp[j]-s*sf[j]);} double K(int j1,int j2){ return ( Y(j1)-Y(j2) ) / ( (X(j1)==X(j2))?1e-9:(X(j1)-X(j2)) ) ;} int main() { int n;scanf("%d%lld",&n,&s); st[0]=0;sf[0]=0; for(int i=1;i<=n;i++) { scanf("%lld%lld",&t[i],&f[i]); st[i]=st[i-1]+t[i]; sf[i]=sf[i-1]+f[i]; } int l=1,r=1;q[1]=0;dp[0]=0; for(int i=1;i<=n;i++) { while(l<r && K(q[l],q[l+1])<=st[i] ) l++; dp[i]=dp[q[l]]+st[i]*(sf[i]-sf[q[l]])+s*(sf[n]-sf[q[l]]); while( l<r && K(q[r-1],q[r] ) >= K(q[r],i) ) r--; q[++r]=i; } printf("%lld\n",dp[n]); return 0; }
- 1
信息
- ID
- 252
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 70
- 已通过
- 39
- 上传者