(纪中)1298. 牛棚【DP】

66 篇文章 1 订阅

在这里插入图片描述
在这里插入图片描述


解题思路

对于奶牛的分布,要求在第1和第s个牛棚上,都有一只奶牛,其次题目给出一个 w = ( s − 1 ) / ( n − 1 ) w=(s-1)/(n-1) w=(s1)/(n1),使相邻的两个奶牛的距离最小是w最大是w+1,又因为首尾都有奶牛,所以在n奶牛形成的 n − 1 n-1 n1个空隙中 v = ( s − 1 ) m o d ( n − 1 ) v=(s-1)mod(n-1) v=(s1)mod(n1)个的长度是 X + 1 X+1 X+1,其余都是X。

先求出 w = ( s − 1 ) / ( n − 1 ) w=(s-1)/(n-1) w=(s1)/(n1) v = ( s − 1 ) m o d ( n − 1 ) v=(s-1)mod(n-1) v=(s1)mod(n1),然后排序。
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(Fi1,j,Fi1,j1)+(i1)w+j+1Ai

其中 ( 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,i1)),初值 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]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值