解题思路
对于奶牛的分布,要求在第1和第s个牛棚上,都有一只奶牛,其次题目给出一个 w = ( s − 1 ) / ( n − 1 ) w=(s-1)/(n-1) w=(s−1)/(n−1),使相邻的两个奶牛的距离最小是w最大是w+1,又因为首尾都有奶牛,所以在n奶牛形成的 n − 1 n-1 n−1个空隙中 v = ( s − 1 ) m o d ( n − 1 ) v=(s-1)mod(n-1) v=(s−1)mod(n−1)个的长度是 X + 1 X+1 X+1,其余都是X。
先求出
w
=
(
s
−
1
)
/
(
n
−
1
)
w=(s-1)/(n-1)
w=(s−1)/(n−1),
v
=
(
s
−
1
)
m
o
d
(
n
−
1
)
v=(s-1)mod(n-1)
v=(s−1)mod(n−1),然后排序。
设
F
i
,
j
Fi,j
Fi,j表示我们已经放置了前i头牛,有
j
j
j段空隙的距离为
X
+
1
X+1
X+1的最小移动距离。
那么转移方程明显就是:
F
i
,
j
=
M
i
n
(
F
i
−
1
,
j
,
F
i
−
1
,
j
−
1
)
+
∣
(
i
−
1
)
∗
w
+
j
+
1
−
A
i
∣
Fi,j=Min(Fi−1,j,Fi−1,j−1)+|(i−1)∗w+j+1−Ai|
Fi,j=Min(Fi−1,j,Fi−1,j−1)+∣(i−1)∗w+j+1−Ai∣
其中 ( 2 < = i < = n , 0 < = j < = M i n ( v , i − 1 ) ) (2<=i<=n,0<=j<=Min(v,i−1)) (2<=i<=n,0<=j<=Min(v,i−1)),初值 F 1 , 0 = A [ 1 ] − 1 F1,0=A[1]−1 F1,0=A[1]−1,其余最大值。
那么 F [ n ] [ v ] F[n][v] F[n][v]就是答案
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define ldb long double
using namespace std;
int n,s,w,v,ans,p[2010],f[2010][2010];
int main(){
freopen("graze2.in","r",stdin);
freopen("graze2.out","w",stdout);
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
sort(p+1,p+n+1);
w=(s-1)/(n-1);
v=(s-1)%(n-1);
memset(f,0x7f,sizeof(f));
f[1][0]=abs(p[1]-1);
for(int i=2;i<=n;i++)
{
f[i][0]=f[i-1][0]+abs(w*(i-1)+1-p[i]);
for(int j=1;j<=min(v,i-1);j++)
{
f[i][j]=min(f[i-1][j],f[i-1][j-1])+abs(w*(i-1)+j+1-p[i]);
}
}
printf("%d",f[n][v]);
}