hdu 3045 Picnic Cows(斜率优化DP)

题目链接:hdu 3045 Picnic Cows

题意:

  1. 有n个奶牛分别有对应的兴趣值,现在对奶牛分组,每组成员不少于t,
  2. 在每组中所有的成员兴趣值要减少到一致,问总共最少需要减少的兴趣值是多少。

题解:

  1. 分析:
    先对n个数进行排序,则可以分析出分组成员一定是连续的
    dp[i]表示前i个数得到的最少值
    则:从j~i作为一组
    dp[i]=dp[j-1]+sum[i]-sum[j-1]-(i-j+1)*s[j];//sum[i]表示前i个数的和
    =>dp[i]=dp[j-1]+sum[i]-sum[j-1]+(j-1)*s[j]-i*s[j];
    由于有i*s[j]这一项,所以无法直接在扫描数组的过程中用单调队列维护:
    dp[j-1]-sum[j-1]+(j-1)*s[j]-i*s[j]的最小值。
    考虑用斜率dp!
    假定k<j<=i-t以j~i作为一组比以k~i作为一组更优
    则:
    dp[j-1]+sum[i]-sum[j-1]-(i-j+1)*s[j] <= dp[k-1]+sum[i]-sum[k-1]-(i-k+1)*s[k]
    =>dp[j-1]+sum[i]-sum[j-1]+(j-1)*s[j]-i*s[j] <= dp[k-1]+sum[i]-sum[k-1]+(k-1)*s[k]-i*s[k]
    =>(dp[j-1]-sum[j-1]+(j-1)*s[j] - (dp[k-1]-sum[k-1]+(k-1)*s[k]))/(s[j]-s[k])<=i;//保证s[j]>=s[k]
    令:
    y1 = dp[j-1]-sum[j-1]+(j-1)*s[j]
    y2 = dp[k-1]-sum[k-1]+(k-1)*s[k]
    x1 = s[j]
    x2 = s[k]
    所以变成了:
    (y1 - y2)/(x1 - x2) <= i;
    斜率!
    只需要维护这个斜率即可

以上转自stephen博客

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef long long ll;
 5
 6 const int N=5e5+7;
 7 int n,t,Q[N];
 8 ll sum[N],s[N],dp[N];
 9
10 ll get_y(int j,int k)
11 {
12     return dp[j-1]-sum[j-1]+(j-1)*s[j]-(dp[k-1]-sum[k-1]+(k-1)*s[k]);
13 }
14
15 ll get_x(int j,int k){return s[j]-s[k];}
16
17 int check(int i,int j,int k)//获取更优的点
18 {
19     return get_y(i,j)*get_x(j,k)<=get_y(j,k)*get_x(i,j);
20 }
21
22 int main()
23 {
24     while(~scanf("%d%d",&n,&t))
25     {
26         F(i,1,n)scanf("%lld",s+i);
27         sort(s+1,s+1+n);
28         F(i,1,n)sum[i]=sum[i-1]+s[i];
29         int en=2*t-1;
30         F(i,t,en)dp[i]=sum[i]-i*s[1];//从t到2*t-1都只能分到一组里
31         int head=1,tail=0,st=2*t;
32         F(i,st,n)
33         {
34             while(head<tail&&check(i-t+1,Q[tail],Q[tail-1]))tail--;
35             Q[++tail]=i-t+1;
36             while(head<tail&&get_y(Q[head+1],Q[head])<=get_x(Q[head+1],Q[head])*i)head++;
37             dp[i]=dp[Q[head]-1]+sum[i]-sum[Q[head]-1]-(i-Q[head]+1)*s[Q[head]];
38         }
39         printf("%lld\n",dp[n]);
40     }
41     return 0;
42 }

时间: 2024-10-11 06:46:24

hdu 3045 Picnic Cows(斜率优化DP)的相关文章

【斜率优化】HDU 3045 Picnic Cows

通道 题意:有n个奶牛分别有对应的兴趣值,现在对奶牛分组,每组成员不少于t,在每组中所有的成员兴趣值要减少到一致,求总共最少需要减少的兴趣值是多少

HDU 3401 Trade(斜率优化dp)

http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:有一个股市,现在有T天让你炒股,在第i天,买进股票的价格为APi,卖出股票的价格为BPi,同时最多买进股票的数量为ASi,卖出股票的数量为BSi.一次交易之后要隔W天之后才能再次交易,并且手上最多持股maxP,问最多可以炒到多少钱. 思路: 首先列一个DP方程: 分别代表不买不卖,买进股票,卖出股票三种情况(上面 (j-k)<=AS[i] , (k-j)<=BS[i]). 那么这里需要枚举r和k

hdu 3507 Print Article —— 斜率优化DP

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m 即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m 于是维护下凸包即可: 写成 double 的 slp 总是不对,把分母乘到对面就对了... 代码如下: #include<iostream> #include<cstdio>

【转】斜率优化DP和四边形不等式优化DP整理

当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重循环跑状态 i,一重循环跑 i 的所有子状态)这样的时间复杂度是O(N^2)而 斜率优化或者四边形不等式优化后的DP 可以将时间复杂度缩减到O(N) O(N^2)可以优化到O(N) ,O(N^3)可以优化到O(N^2),依次类推 斜率优化DP和四边形不等式优化DP主要的原理就是利用斜率或者四边形不等式等数学方法 在所有要判断的子状态中迅速做出判断,所以这里的优化其实是省去了枚举

HDU 3507 单调队列 斜率优化

斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方法来做,但是该题要求的是区间和的平方,于是要转换单调的计算方法为斜率,也就是凸线. 其他就是最基本的单调DP /** @Date : 2017-09-04 15:39:05 * @FileName: HDU 3507 单调队列 斜率优化 DP.cpp * @Platform: Windows * @

HDU3045 Picnic Cows(斜率优化DP)

Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2192    Accepted Submission(s): 675 Problem Description It’s summer vocation now. After tedious milking, cows are tired and wish to t

hdu 2993 MAX Average Problem (斜率优化dp入门)

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5855    Accepted Submission(s): 1456 Problem Description Consider a simple sequence which only contains positive integers as

Print Article hdu 3507 一道斜率优化DP 表示是基础题,但对我来说很难

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 4990    Accepted Submission(s): 1509 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程很容易想出来,dp[i][j] 表示前 j 个数分成 i 组.但是复杂度是三次方的,肯定会超时,就要对其进行优化. 有两种方式,一种是斜率对其进行优化,是一个很简单的斜率优化 dp[i][j] = min{dp[i-1][k] - w[k] + sum[k]*sum[k] - sum[k]*sum[