第一道斜率最佳化dp,看著別人的報告做的,做之前建議看一下04年周源的《淺談數形結合思想在資訊學競賽中的應用》論文 http://wenku.baidu.com/view/f6421ce8b8f67c1cfad6b8ac.html
斜率最佳化其實就是把每個狀態看作直角座標繫上離散的點抽象出x,y 表示斜率 (y2 - y1) / (x2 - x1) 於一個關係狀態i個函數的關係,然後維護點見斜率的上凸性或者下凸性。具體的情況要看於i有關的函數的單調性。
說一些注意事項:
注意斜率盡量中乘法,不要中實數,如有必要全用long long,以免溢出。注意 x2 - x1可能小於0不等式的負號要改變!
這道是論文的例題,求的是大於等於k範圍的最大均值,所以需要造出下凹折線......
#define N 100005double sum[N];int que[N],head,tail;int main(){ int n,k; while(scanf("%d%d",&n,&k) != -1){ int i,j; sum[0] = 0; for(i=1;i<=n;i++){ int a; scanf("%d",&a); sum[i] = sum[i-1]+a*1.0; } head = tail = 0; que[0] = 0; double ans = 0.0; for(i=k;i<=n;i++){ int now = i-k;//i-k點跟第i點比較,保證範圍>=k //去掉上凸點 while(head<tail){ double y1 = sum[que[tail]] - sum[que[tail-1]]; double x1 = que[tail] - que[tail-1]; double y2 = sum[now] - sum[que[tail]]; double x2 = now - que[tail]; if(y1*x2>=y2*x1)tail--; else break; } que[++tail] = now; //去掉下凹折線的斜率小的點,因為這些點對後面的最優解沒有貢獻 while(head<tail){ double y1 = sum[que[head]] - sum[i]; double x1 = que[head] - i; double y2 = sum[que[head+1]] - sum[i]; double x2 = que[head+1] - i; if(y1*x2<=y2*x1)head++; else break; } double tmp = (sum[que[head]] - sum[i])/((que[head] - i)*1.0); ans = max(ans,tmp); } printf("%.2lf\n",ans); } return 0;}
mark一下這個bloghttp://www.cnblogs.com/ronaflx/archive/2011/02/05/1949278.html,決定這幾天每天都做1~2到斜率dp,好好吸收它的思維精髓!