HDU 3045 Picnic Cows(斜率优化DP)
这是个很明显的DP题目,排序之后容易想到DP方程为dp【i】 = dp【j】 + w【j + 1,i】
然而4*10^5次方明显TLE,必须得优化,因为是一维的状态表示,所以四边形优化应该不可行(个人做题太少了,没见过一维的四边形优化)
另外w函数和j有关,所以单调队列不可行了,只能往斜率优化想了,斜率优化证明还算容易吧,证出来之后就相当于模板了
#include<stdio.h> #include<string.h> #include<algorithm> #define INF 0x7ffffffffffLL #define LL __int64 using namespace std; const int maxn = 400005; LL moo[maxn],q[maxn]; LL dp[maxn],sum[maxn]; LL n,m; LL get_y(LL i,LL j){ return (dp[i] + (i) * moo[i + 1] - sum[i] ) - (dp[j] + (j) * moo[j + 1] - sum[j]); } LL get_x(LL i,LL j){ return moo[i + 1] - moo[j + 1]; } LL get_dp(LL j,LL t) { return dp[j] + sum[t] - sum[j] - (t - j) * moo[j + 1]; } void solve(); int main() { int i; while(scanf("%I64d%I64d",&n,&m) != EOF){ for(i = 1;i <= n;i ++) scanf("%I64d",&moo[i]); sort(moo + 1,moo + 1 + n); /* for(i = 1;i <= n;i ++) printf("%d ",moo[i]); putchar('\n');*/ for(i = 1;i <= n;i ++) sum[i] = sum[i - 1] + moo[i]; memset(dp,0,sizeof(dp)); solve(); /* for(i = 1;i <= n;i ++) printf("I:%d DP:%I64d get:%I64d\n",i,dp[i],get_dp(0,i));*/ } return 0; } void solve() { LL head,tail,i; head = tail = 0; for(i = 1;i < m; i++) dp[i] = INF; q[0] = 0; for(i = m;i <= n;i ++){ LL p = i - m; while(head < tail){ LL x1 = get_x(q[tail - 1],q[tail]); LL y1 = get_y(q[tail - 1],q[tail]); LL x2 = get_x(q[tail],p); LL y2 = get_y(q[tail],p); if(y1 * x2 >= y2 * x1) tail --; else break; } q[++ tail] = p; while(head < tail){ LL a = get_dp(q[head],i); LL b = get_dp(q[head + 1],i); if(a > b) head ++; else break; } // if(i == 7) printf("HEAD:%I64d\n",q[head]); dp[i] = get_dp(q[head],i); } printf("%I64d\n",dp[n]); }