思路:首先因为要让距离尽量大,所以奶牛1一定在1号牛棚,奶牛n一定在s号牛棚,然后考虑dp。
因为总距离为s-1,然后要使长度为d的段数尽量多,那么剩下的一定就是d+1的段数,也就是s-(n-1)*d。
然后f[i][j]表示保证前i个牛棚合法且前面长为d+1的段数为j的答案,然后第i个牛棚的位置其实就是(i-1)*d+j。
又因为第i-1个牛棚只可能是相隔d或d-1,所以有f[i][j]=min(f[i-1][j],f[i-1][j-1])+abs(a[i]-(i-1)*d-j)
答案就是f[n][m]。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 1505 int n,s; int a[maxn]; int f[maxn][maxn]; inline int read(){ int x=0;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()); for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x; } inline void print(int x){ if (x>=10) print(x/10); putchar(x%10+'0'); } int main(){ n=read(),s=read();int d=(s-1)/(n-1),m=s-(n-1)*d; for (int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); memset(f,63,sizeof(f)),f[1][1]=a[1]-1; for (int i=2;i<=n;i++) for (int j=1;j<=m&&j<=i;j++) f[i][j]=min(f[i-1][j],f[i-1][j-1])+abs(a[i]-d*(i-1)-j); print(f[n][m]); return 0; }