Division HDU - 3480 斜率dp

Posted qingyuyyyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Division HDU - 3480 斜率dp相关的知识,希望对你有一定的参考价值。

//将含有N个元素的一个集合分成M个子集,使得每个子集的最大值与最小值平方差的和最小。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e4+50;
const int maxm = 5e3+50;
ll dp[maxn][maxm] ,v[maxn] ;
int n ,m ;
int q[maxn] ,r,l ;
ll getdp(int i,int j,int k) {
    return dp[k][j-1] + (v[i] - v[k + 1]) * (v[i] - v[k + 1]);
}
ll y(int j,int k,int q) {
    return dp[k][j-1] + v[k + 1] * v[k + 1] - (dp[q][j-1] + v[q + 1] * v[q + 1]);
}
ll x(int k,int q) {
    return 2 * ( v[k + 1] - v[q + 1] );
}
int main() {
    int t ,ncase = 1 ;
    cin>>t;
    while(t--) {
        scanf("%d %d",&n ,&m );
        for (int i = 1; i<=n; i++) 
            scanf("%lld",&v[i] );
        sort(v + 1 ,v + n + 1 );
        for (int i = 1; i<=n; i++) 
            dp[i][1] = (v[i] - v[1]) * (v[i] - v[1]);
        for (int i = 2; i<=m; i++) {
            l = r = 0;
            q[0] = i - 1;
            for (int j = i; j<=n; j++) {
                while(l  < r && y(i ,q[l+1] ,q[l]) < x(q[l+1] ,q[l]) * v[j] ) 
                    l ++;
                dp[j][i] = getdp(j ,i ,q[l] );
                while(l  < r && y(i ,q[r] ,q[r-1]) * x(j ,q[r]) >= y(i ,j ,q[r]) * x(q[r] ,q[r-1]) ) 
                    r --;
                q[++r] = j;
            }
        }
        printf("Case %d: ",ncase++);
        printf("%lld
",dp[n][m]);
    }
    return 0;
}

以上是关于Division HDU - 3480 斜率dp的主要内容,如果未能解决你的问题,请参考以下文章

Division HDU - 3480 斜率dp

hdu 3480 Division(斜率优化)

HDU 3480 斜率dp

HDU-3480 Division (四边形不等式优化DP)

HDU - 3480 Division

HDU3480:Division——题解