分析:
首先,连续选择一段必定最优...
区间DP,f[i][j]表示从i开始,连续j个被吃掉了,并且,牛在i处,g[i][j]则表示在i+j-1处
f[i][j]可以从g[i+1][j]和f[i+1][j]转移,g[i][j]可以从g[i][j-1]和f[i][j-1]转移,转移方程:
f[i][j]=min(f[i+1][j]+(n-j+1)*(a[i+1]-a[i]),g[i+1][j]+(n-j+1)*(a[i+j-1]-a[i]));g[i][j]同样...
附上代码:
#include <cstdio> #include <cmath> #include <algorithm> #include <cstdlib> #include <cstring> #include <queue> #include <iostream> #include <set> using namespace std; #define N 1005 long long f[N][N],g[N][N]; int n,L,a[N]; int main() { memset(f,0x3f,sizeof(f));memset(g,0x3f,sizeof(g)); scanf("%d%d",&n,&L); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1); int p=lower_bound(a+1,a+n+1,L)-a; if(p!=1)f[p-1][1]=g[p-1][1]=1ll*n*(L-a[p-1]); if(a[p]>=L)f[p][1]=g[p][1]=1ll*n*(a[p]-L); for(int i=2;i<=n;i++) { for(int j=1;j<=n-i+1;j++) { int k=i+j-1; f[j][i]=min(f[j+1][i-1]+(n-i+1)*(a[j+1]-a[j]),g[j+1][i-1]+(n-i+1)*(a[k]-a[j])); g[j][i]=min(f[j][i-1]+(a[k]-a[j])*(n-i+1),g[j][i-1]+(a[k]-a[k-1])*(n-i+1)); } } printf("%lld ",min(f[1][n],g[1][n])); return 0; }