题目大意:
输入n,s;n头牛 s个栅栏
输入n头牛的初始位置
改变他们的位置,满足
1.第一头与最后一头的距离尽量大
2.相邻两头牛之间的距离尽量满足 d=(s-1)/(n-1),偏差不超过1
3.移动的总步数尽量小
https://blog.csdn.net/BlackJack_/article/details/73527208
首先因需要尽量满足d
1.若整除则全部为d即可
2.若不整除则说明存在偏差,则有些距离 d 有些距离 d+1 即可
除了第一头牛移到1 最后一头牛移到s之外
其余第 i 头牛最佳位置应为 d*(i-1)
若到目前为止位置偏差值为 j ,则应为 d*(i-1)+ j
则这头牛应该移动 | a[ i ]-(d*(i-1)+j)| 即 abs( a[ i ] - ( i-1 ) * d - j )
那么可由min( dp[ i-1 ][ j ],dp[ i-1 ][ j-1 ] )转移而来
前者是 i-1 与 i 距离 d 的情况,而后者是 i-1 与 i 距离 d+1 的情况
#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; int a[1505], dp[2][1505]; // 滚动数组 int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); int d=(m-1)/(n-1);// 最佳间距 m=m-(n-1)*d;// 总偏差间距+1 (方便推算) memset(dp,INF,sizeof(dp)); /// dp[i][j] 表到第i个时偏差为j的移动次数 dp[1][1]=a[1]-1;// 偏差从1开始 则m对应的恰好为总偏差间距 for(int k=2;k<=n;k++) { int i=k%2; for(int j=1;j<=k&&j<=m;j++) dp[i][j]=min(dp[(!i)][j-1],dp[(!i)][j]) +abs(a[k]-(k-1)*d-j); } printf("%d ",dp[n%2][m]); } return 0; }