题意,给你10000个牛的位置,牛之间的距离越远,他的产奶量就越高。FJ是一个很有爱的萌系小骚年,他希望把牛之间的距离安排得尽量远,并且使用的时间最短。
解法,题目中的D很容易能知道是l/(n-1),那么令dp[i][j],i表示放好前i头牛,并把第i头牛放在j位置上所需要的最小时间。
DP方程:dp[i][j]={dp[i-1][k]+abs(p[i]-j),0<k<l}因为不是所有的0<k<l都能放第i头牛,所以为了节约时间,我们把k的上界和下界算出来放在p_low和p_up里面。
据说用二维数组会TLE,所以我们调整一下里面一层for循环的顺序,用一维数组的形式来dp,就解决了这个问题。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[110000],p[11000],p_low[11000],p_up[11000];
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int abs(int n)
{
return n>0?n:-n;
}
int main()
{
int n,i,j,l,d,t;
scanf("%d%d",&n,&l);
for (i=0; i<n; i++)
{
scanf("%d",p+i);
}
if (n == 1)
{
printf("0\n");
return 0;
}
d=l/(n-1);
//找出每头牛可以摆放的位置,存放在p_low,p_up数组里面
p_low[0]=0;
p_up[0]=0;
p_low[n-1]=l;
p_up[n-1]=l;
for (i=1; i<n-1; i++)
{
p_low[i]=max(d*i,l-(d+1)*(n-i-1));
if (p_low[i] < 0)
p_low[i]=0;
p_up[i]=min((d+1)*i,l-d*(n-i-1));
if (p_up[i] > l)
p_up[i]=l;
}
//以一维的形式进行DP
memset(dp,0x3f,sizeof(dp));
dp[0]=p[0];
for (i=1; i<n; i++)
{
for (j=p_up[i]; j>=p_low[i]; j--)
{
t=j-d;
dp[j]=0x3f3f3f3f;
if (t >= p_low[i-1] && t <= p_up[i-1]) //前一个的位置也必须在low和up间
dp[j]=min(dp[j],dp[t]+abs(j-p[i]));
t--;
if (t >= p_low[i-1] && t <= p_up[i-1])
dp[j]=min(dp[j],dp[t]+abs(j-p[i]));
}
}
printf("%d\n",dp[l]);
}