您的位置:首页 > 其它

hdu 3480 Division 斜率优化dp

2016-10-02 21:39 453 查看

题目链接

题意:

给出n个数,分为m组,求min{∑(Max−Min)2} N (≤ 10,000) and M (≤ 5,000)

解法:序列划分+斜率优化

代码:

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxN= 10000    ;
const int maxM= 5000    ;
ll a[maxN+10];
ll dp[maxM+5][maxN+5];
int q[maxN+5],M,N;

ll getY(int j,int m)   { return  dp[m-1][j]+a[j+1]*a[j+1];  }
ll getX(int j,int m)   { return  a[j+1];  }
ll Cross(int j2,int j1,int i,int m)
{
return   (getX(j1,m)-getX(j2,m))*(getY(i,m)-getY(j1,m))-(getX(i,m)-getX(j1,m))*(getY(j1,m)-getY(j2,m));

}

ll fun(int j2,int j1,int i,int m)
{
return  ( getY(j1,m)-getY(j2,m) )-2*a[i]*(getX(j1,m)-getX(j2,m));
}
void solve()
{

dp[0][0]=0;
for(int m=1;m<=M;m++)
{

int front=0,rear=0;
q[rear++]=m-1;
for(int i=m;i<=N;i++)
{
while(rear-front>=2&&fun(q[front],q[front+1],i,m)<=0 )  front++;

int j=q[front];
dp[m][i]=dp[m-1][j]+  (a[i]-a[j+1])*(a[i]-a[j+1]);

if(m>1)
{
while(rear-front>=2&&Cross(q[rear-2],q[rear-1],i,m)<=0 )  rear--;

q[rear++]=i;

}
}
}

printf("%lld\n",dp[M]
);
}
int main()
{
std::ios::sync_with_stdio(false);
int T,kase=0;cin>>T;
while(T--)
{
cin>>N>>M;

for1(i,N)  cin>>a[i];
sort(a+1,a+1+N);

printf("Case %d: ",++kase);
solve();
}
return 0;
}

/*
213
4 2
4 7 10 1

4 2
1 4 7 10
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp