zoukankan      html  css  js  c++  java
  • hdu3480 Division(斜率优化+二维DP)

    点击打开链接

    题意:给你一些数,把这些数分成M组,每组的花费是这组的 (max-min)^2。求最小花费

    思路:

    斜率优化+二维DP

    f[i][m] 表示将前i个分作m个集合所得最小消费

    首先应该排序,假设1,2,3,5,4   第四个数是5,花费一定比是4大。【贪心】

    f[i][m] = min{f[j][m-1]+(a[i]-a[j+1])*(a[i]-a[j+1])};   排序是为了让a[i]-a[j+1]总是最小的

    若有j>k,且决策j优于决策k则有:

    f[j][j-1]-f[k][j-1]+sq(a[j+1])-sq(a[k+1]) <= 2*(a[j+1]-a[k+1])*a[i]

    先进行m循环枚举f[][m],每一层维护一个单调队列即可。

    乘除耗费时间悬殊,如果直接除这个题就超时了。


    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define mem(a) memset(a,0,sizeof(a))
     5 #define mp(x,y) make_pair(x,y)
     6 const int INF = 0x3f3f3f3f;
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     8 inline ll read(){
     9     ll x=0,f=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 //////////////////////////////////////////////////////////////////////////
    15 const int maxn = 1e4+10;
    16 int n,M;
    17 int a[maxn],f[maxn][5005],q[maxn];
    18 int getup(int j,int k,int m){
    19     return f[j][m-1]-f[k][m-1]+a[j+1]*a[j+1]-a[k+1]*a[k+1];
    20 }
    21 
    22 int getdown(int j,int k,int m){
    23     return 2*(a[j+1]-a[k+1]);
    24 }
    25 
    26 int main(){
    27     int T=read();
    28     for(int cas=1; cas<=T; cas++){
    29         n=read(),M=read();
    30         for(int i=1; i<=n; i++)
    31             a[i]=read();
    32         sort(a+1,a+1+n);
    33         for(int i=1; i<=n; i++) f[i][1] = (a[i]-a[1])*(a[i]-a[1]);
    34 
    35         for(int m=2; m<=M; m++){
    36             int L=0,R=0;
    37             for(int i=1; i<=n; i++){
    38                 while(L<R && getup(q[L+1],q[L],m) <= a[i]*getdown(q[L+1],q[L],m)) L++;
    39                 int j = q[L];
    40                 f[i][m] = f[j][m-1]+(a[i]-a[j+1])*(a[i]-a[j+1]);
    41                 while(L<R && getup(i,q[R],m)*getdown(q[R],q[R-1],m) <= getup(q[R],q[R-1],m)*getdown(i,q[R],m)) R--;
    42                 q[++R] = i;
    43             }
    44         }
    45 
    46         cout << "Case " << cas << ": " << f[n][M] << endl;
    47     }
    48 
    49     return 0;
    50 }





  • 相关阅读:
    php详解和优化
    接口
    抽象类
    对象转型
    面向对象2
    Super关键字
    Object类介绍
    有效处理java异常的三个原则
    this关键字
    equals方法
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827708.html
Copyright © 2011-2022 走看看