hdu 3480

时间:2021-08-21 15:48:51

斜率dp

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 10005
#define maxm 5005
using namespace std;
int dp[maxn][maxm];
int q[maxn*];
int num[maxn]; bool check(int j,int tail,int i)
{
int yk=dp[q[tail-]][j-]+num[q[tail-]+]*num[q[tail-]+];
int yj=dp[q[tail]][j-]+num[q[tail]+]*num[q[tail]+];
int yi=dp[i][j-]+num[i+]*num[i+];
int xk=*num[q[tail-]+];
int xj=*num[q[tail]+];
int xi=*num[i+];
if((yi-yk)*(xj-xk)<=(yj-yk)*(xi-xk))return ;
return ;
} bool get(int head,int j,int i)
{
int y1=dp[q[head]][j-]+num[q[head]+]*num[q[head]+];
int y2=dp[q[head+]][j-]+num[q[head+]+]*num[q[head+]+];
int x1=num[q[head]+];
int x2=num[q[head+]+];
if((y2-y1)<=*num[i]*(x2-x1))return ;
return ;
} int main()
{
int n,m,t;
int ca=;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&num[i]);
sort(num+,num+n+);
int tail,head;
for(int i=;i<=n;i++)
dp[i][]=(num[i]-num[])*(num[i]-num[]);
for(int j=;j<=m;j++)
{
head=tail=;
q[++tail]=j-;
for(int i=j;i<=n;i++)
{
while(tail-head>&&check(j,tail,i))tail--;
q[++tail]=i;
while(tail-head>&&get(head+,j,i))head++;
int best=q[head+];
dp[i][j]=dp[best][j-]+(num[i]-num[best+])*(num[i]-num[best+]); }
}
printf("Case %d: %d\n",ca++,dp[n][m]);
}
return ;
}

四边形不等式优化:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10005
#define maxm 5005
#define inf 99999999
using namespace std; int dp[maxn][maxm];
int s[maxn][maxm];
int num[maxn]; int main()
{
int n,m;
int t,ca=;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
scanf("%d",&num[i]);
sort(num+,num++n);
dp[][]=;
for(int i=; i<=n; i++)
{
dp[i][]=(num[i]-num[])*(num[i]-num[]);
}
for(int j=; j<=m; j++)
{
s[n+][j]=n-;
for(int i=n; i>=j; i--)
{
dp[i][j]=inf;
for(int k=s[i][j-]; k<=s[i+][j]; k++)
{
int tmp=dp[k][j-]+(num[i]-num[k+])*(num[i]-num[k+]);
if(dp[i][j]>tmp)
{
s[i][j]=k;
dp[i][j]=tmp;
}
}
}
}
printf("Case %d: %d\n",ca++,dp[n][m]);
}
return ;
}