#斜率优化dp# [poj 1180] Batch Scheduling

题目

http://poj.org/problem?id=1180


解题思路

n 2 n^2 n2 d p : dp: dp: f [ i ] = m i n ( f [ j ] + s u m T [ i ] ∗ ( s u m C [ i ] − s u m C [ j ] ) + S ∗ ( s u m C [ N ] − s u m C [ j ] ) ) f[i]=min(f[j]+sumT[i]*(sumC[i]-sumC[j])+S*(sumC[N]-sumC[j])) f[i]=min(f[j]+sumT[i](sumC[i]sumC[j])+S(sumC[N]sumC[j]))
f [ j ] = ( S + s u m T [ i ] ) ∗ s u m C [ j ] + f [ i ] − s u m T [ i ] ∗ s u m C [ i ] − S ∗ s u m C [ n ] f[j]=(S+sumT[i])*sumC[j]+f[i]-sumT[i]*sumC[i]-S*sumC[n] f[j]=(S+sumT[i])sumC[j]+f[i]sumT[i]sumC[i]SsumC[n]
每个待求解的状态 f [ i ] f[i] f[i]都对应着一条直线的截距,直线的斜率是 S + s u m T [ i ] S+sumT[i] S+sumT[i],截距未知。当截距最小化, f [ i ] f[i] f[i]也取到最小值。
有三个决策点 j 1 , j 2 , j 3 ( j 1 < j 2 < j 3 ) j1,j2,j3(j1<j2<j3) j1,j2,j3(j1<j2<j3)
j 2 j2 j2有可能成为最优决策,当且仅当 f [ j 2 ] − f [ j 1 ] s u m C [ j 2 ] − s u m C [ j 1 ] < f [ j 3 ] − f [ j 2 ] s u m C [ j 3 ] − s u m C [ j 2 ] \frac{f[j2]-f[j1]}{sumC[j2]-sumC[j1]}<\frac{f[j3]-f[j2]}{sumC[j3]-sumC[j2]} sumC[j2]sumC[j1]f[j2]f[j1]<sumC[j3]sumC[j2]f[j3]f[j2]
用单调队列维护 “ 下 凸 壳 ” “下凸壳”


代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; 
int n,s,t,c,sumt[10001],sumc[10001],f[10001],q[10001];
int main(){
	scanf("%d%d",&n,&s); 
	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)); 
	int l=1,r=1; q[1]=0; f[0]=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("%d",f[n]); 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值