zoukankan      html  css  js  c++  java
  • HDU 3045 picnic cows(斜率DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3045

    题目大意:有n个数,可以把n个数分成若干组,每组不得小于m个数,每组的价值=除了该组最小值以外每个值-最小值之和,求使得所有组的价值之和的最小值。

    解题思路:将n个数按从小到大排序,处理前i为前缀和为sum[i],则可得出状态转移方程:dp[i]=min{dp[j]+sum[i]-sum[j+1]-a[j+1]*(i-j-1)}(0<=j<i-m+1),再用斜率DP优化即可。

         注意:一定要判断j是否大于等于m,因为至少m才能算一组奶牛,不然会出错。

    代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 typedef long long LL;
     7 const int N=5e5+5;
     8 
     9 int head,tail;
    10 LL sum[N],dp[N],a[N],q[N];;
    11 
    12 LL getUP(int k,int j){
    13     return dp[j]+a[j+1]*(j+1)-sum[j+1]-dp[k]-a[k+1]*(k+1)+sum[k+1];
    14 }
    15 
    16 LL getDOWN(int k,int j){
    17     return a[j+1]-a[k+1];
    18 }
    19 
    20 //dp[i]=min{dp[j]+sum[i]-sum[j+1]-a[j+1]*(i-j-1)}
    21 LL getDP(int i,int j){
    22     return dp[j]+sum[i]-sum[j+1]-a[j+1]*(i-j-1);
    23 }
    24 
    25 int main(){
    26     int n,m;
    27     while(~scanf("%d %d",&n,&m)){
    28         memset(dp,0x3f3f3f3f,sizeof(dp));
    29         for(int i=1;i<=n;i++){
    30             scanf("%lld",&a[i]);
    31         }
    32         sort(a+1,a+1+n);
    33         for(int i=1;i<=n;i++){
    34             sum[i]=sum[i-1]+a[i];
    35         }
    36         dp[0]=0;
    37         head=tail=0;
    38         q[tail++]=0;
    39         for(int i=1;i<=n;i++){
    40             while(head+1<tail&&getUP(q[head],q[head+1])<=i*getDOWN(q[head],q[head+1])){
    41                 head++;
    42             }
    43             dp[i]=getDP(i,q[head]);
    44             int j=i-m+1;
    45             //注意z这个判断,因为状态转移,也就是分组,至少要保证第一组有m头牛。 
    46             if(j<m)
    47                 continue;
    48             while(head+1<tail&&getUP(q[tail-1],j)*getDOWN(q[tail-2],q[tail-1])<=getUP(q[tail-2],q[tail-1])*getDOWN(q[tail-1],j)){
    49                 tail--;
    50             }
    51             q[tail++]=j;
    52         }
    53         printf("%lld
    ",dp[n]);
    54     }
    55 
    56     return 0;
    57 }
  • 相关阅读:
    每日日报40
    每日日报39
    每日日报38
    vue 0点定时网络请求
    js reduce
    时间选择器 element
    CTF-WEB:PHP 变量
    CTF-WEB:PHP 反序列化
    Java 异常类与捕获异常
    Java 面向对象:内部类
  • 原文地址:https://www.cnblogs.com/fu3638/p/7850374.html
Copyright © 2011-2022 走看看