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

題目

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


解題思路

n2n^2dp:dp: 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+sumT[i])sumC[j]+f[i]sumT[i]sumC[i]SsumC[n]f[j]=(S+sumT[i])*sumC[j]+f[i]-sumT[i]*sumC[i]-S*sumC[n]
每個待求解的狀態f[i]f[i]都對應着一條直線的截距,直線的斜率是S+sumT[i]S+sumT[i],截距未知。當截距最小化,f[i]f[i]也取到最小值。
有三個決策點j1,j2,j3(j1<j2<j3)j1,j2,j3(j1<j2<j3)
j2j2有可能成爲最優決策,當且僅當f[j2]f[j1]sumC[j2]sumC[j1]<f[j3]f[j2]sumC[j3]sumC[j2]\frac{f[j2]-f[j1]}{sumC[j2]-sumC[j1]}<\frac{f[j3]-f[j2]}{sumC[j3]-sumC[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]); 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章