HDU 3045
2013-08-12 21:44
281 查看
斜率优化dp
第一次做斜率优化dp,惯例写详细点。。
题意:给你N个数,将它们分成若干组,要求每组至少包含T个数。将每一组的数全部变为该组最小的数。进行合适的分组,使得数字的减小量的总和最小。求这个最小值。
首先很容易想到将这N个数字从小到大排序。递推式就很容易出来:dp[j] = min(dp[i] + sum[j] - sum[i] - num[i+1]*(j-i)) i<=j-T 其中,dp[i] 表示将前 i 个数分组的最小费用,sum[i]表示前 i 个数的和,num[i]表示第 i 个数。由于题目给出的 N 最大有 4*10^5 直接推,两个for循环超时妥妥的。这里用到了斜率优化,将复杂度从O(n^2) 降到O(n)
假设 i<j<p ,那么对于 p 从i,j递推来的两个值分别为:dp[i] + sum[p] - sum[i] - num[i+1]*(p-i) 和 dp[j] + sum[p] - sum[j] - num[j+1]*(p-j) 。如果 i 不优于 j ,那么就一定满足:dp[j] + sum[p] - sum[j] - num[j+1]*(p-j) <= dp[i] + sum[p] - sum[i] - num[i+1]*(p-i) 整理后得:dp[j]-sum[j]+num[j+1]*j
- (dp[i]-sum[i]+num[i+1]*i) <= (num[j+1]-num[i+1])*p 令yj=dp[j]-sum[j]+num[j+1]*j ,xj=num[j+1] 那么上式就能整理为:(yj-yi)/(xj-xi) <= p 左边就是一个斜率表达式了。方便描述,这里记g[i,j] = (yj-yi)/(xj-xi)。如何利用这个斜率优化呢?
优化1:假设 i<j<k<p , 如果g[j,k]<=g[i.j] 那么可以忽略点 j 。原因如下:当g[j,k]<=p ,对于 p 来说,j 不优于 k ;当 g[j,k]>p ,那么g[i,j]>=g[j,k]>p,对于 p 来说 i 优于 j 。去掉所有类似 j 的点后,斜率呈现严格递增。
基于优化1有优化2:假设 i<j<p<q , 如果g[i,j]<=p ,那么对于点 p ,i 不优于 j ;对于点 q ,g[i,j]<=p<q ,i 劣于 j 。假设我们找到了 p 的最优解 j ,那么 j 以前的解一定不是 q 的最优解。
有了这两个优化,复杂度就成功的降到了O(n)。结合代码细细体会。over
第一次做斜率优化dp,惯例写详细点。。
题意:给你N个数,将它们分成若干组,要求每组至少包含T个数。将每一组的数全部变为该组最小的数。进行合适的分组,使得数字的减小量的总和最小。求这个最小值。
首先很容易想到将这N个数字从小到大排序。递推式就很容易出来:dp[j] = min(dp[i] + sum[j] - sum[i] - num[i+1]*(j-i)) i<=j-T 其中,dp[i] 表示将前 i 个数分组的最小费用,sum[i]表示前 i 个数的和,num[i]表示第 i 个数。由于题目给出的 N 最大有 4*10^5 直接推,两个for循环超时妥妥的。这里用到了斜率优化,将复杂度从O(n^2) 降到O(n)
假设 i<j<p ,那么对于 p 从i,j递推来的两个值分别为:dp[i] + sum[p] - sum[i] - num[i+1]*(p-i) 和 dp[j] + sum[p] - sum[j] - num[j+1]*(p-j) 。如果 i 不优于 j ,那么就一定满足:dp[j] + sum[p] - sum[j] - num[j+1]*(p-j) <= dp[i] + sum[p] - sum[i] - num[i+1]*(p-i) 整理后得:dp[j]-sum[j]+num[j+1]*j
- (dp[i]-sum[i]+num[i+1]*i) <= (num[j+1]-num[i+1])*p 令yj=dp[j]-sum[j]+num[j+1]*j ,xj=num[j+1] 那么上式就能整理为:(yj-yi)/(xj-xi) <= p 左边就是一个斜率表达式了。方便描述,这里记g[i,j] = (yj-yi)/(xj-xi)。如何利用这个斜率优化呢?
优化1:假设 i<j<k<p , 如果g[j,k]<=g[i.j] 那么可以忽略点 j 。原因如下:当g[j,k]<=p ,对于 p 来说,j 不优于 k ;当 g[j,k]>p ,那么g[i,j]>=g[j,k]>p,对于 p 来说 i 优于 j 。去掉所有类似 j 的点后,斜率呈现严格递增。
基于优化1有优化2:假设 i<j<p<q , 如果g[i,j]<=p ,那么对于点 p ,i 不优于 j ;对于点 q ,g[i,j]<=p<q ,i 劣于 j 。假设我们找到了 p 的最优解 j ,那么 j 以前的解一定不是 q 的最优解。
有了这两个优化,复杂度就成功的降到了O(n)。结合代码细细体会。over
#include<stdio.h> #include<iostream> #include<algorithm> using namespace std; #define Maxn 400010 int N,T,q[Maxn],head,tail; long long num[Maxn],dp[Maxn],sum[Maxn]; long long getDp(int i,int j); long long getY(int i,int j); long long getX(int i,int j); int main() { while(scanf("%d%d",&N,&T)!=EOF) { dp[0]=sum[0]=num[0]=head=tail=0; q[tail++]=0; for(int i=1;i<=N;i++) { scanf("%I64d",&num[i]); sum[i]=sum[i-1]+num[i]; } sort(num+1,num+1+N); for(int i=T;i<=N;i++) { while(head+1<tail && getY(q[head],q[head+1])<=i*getX(q[head],q[head+1])) head++; dp[i]=getDp(q[head],i); int j=i-T+1; if(j<T) continue; while(head+1<tail && getY(q[tail-1],j)*getX(q[tail-2],q[tail-1])<=getY(q[tail-2],q[tail-1])*getX(q[tail-1],j)) tail--; q[tail++]=j; } printf("%I64d\n",dp ); } return 0; } long long getDp(int i,int j) { return dp[i]+sum[j]-sum[i]-num[i+1]*(j-i); } long long getY(int i,int j) { return dp[j]-sum[j]+num[j+1]*j-(dp[i]-sum[i]+num[i+1]*i); } long long getX(int i,int j) { return num[j+1]-num[i+1]; }
相关文章推荐
- HDU 3045 Picnic Cows(斜率优化DP)
- Hdu 3045
- hdu 3045 斜率优化DP
- HDU 3045 Picnic Cows(斜率优化DP)
- dp斜率优化 Hdu 3045(Picnic Cows)题解
- HDU-3045 Picnic Cows 【DP+斜率优化】
- HDU 3045 MAX Average Problem
- hdu 3045 Picnic Cows 斜率优化dp
- HDU 3962 / HIT 3045 Microgene--ac自动机 动态规划
- HDU 3045 Picnic Cows 斜率优化DP
- HDU 3045 (斜率优化)
- HDU - 3045 Picnic Cows(斜率优化)
- HDU 3045 Picnic Cows
- HDU-3045 Picnic Cows 斜率优化DP
- HDU 3045 DP 斜率优化 Picnic Cows
- HDU 4296 Buildings POJ 3045 Cow Acrobats(贪心)
- hdu 3045 Picnic Cows 斜率优化 dp中有间隔限定
- HDU - 3045 Picnic Cows
- hdu 3045 Picnic Cows(斜率优化DP)
- hdu 3045 Picnic Cows(斜率优化dp)