http://www.lydsy.com/JudgeOnline/problem.php?id=3405
n个牛棚,n-1段
因为要求距离尽量大,而且尽可能多的为d
所以:
第1个牛棚一定在位置1
最后一个牛棚一定在位置s
每段距离不是d就是d+1
有s-(n-1)*d-1段 d+1,其余段距离为d
dp[i][j] 表示前i个牛棚,有j段距离为d+1
那么第i个牛棚的位置就是d*(i-1)+j+1
第i个牛棚要么与上一个距离为d,要么距离为d-1
所以转移方程为 dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+abs(pos[i]-(i-1)*d-j-1);
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 1501 int dp[N][N]; int pos[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int main() { int n,s; read(n); read(s); for(int i=1;i<=n;++i) read(pos[i]); int d=(s-1)/(n-1); int m=s-(n-1)*d-1; sort(pos+1,pos+n+1); memset(dp,63,sizeof(dp)); dp[1][0]=pos[1]-1; for(int i=2;i<=n;++i) { dp[i][0]=dp[i-1][0]+abs(pos[i]-d*(i-1)-1); for(int j=1;j<=m && j<i;++j) dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+abs(pos[i]-(i-1)*d-j-1); } cout<<dp[n][m]; }