题解 P2893 【[USACO08FEB]Making the Grade G】
DP
首先看数据范围,
单调不降或者单调不升,我们很容易想到DP。
我们想要花费最小,说明尽可能让每个数动的幅度小一点。能不动就不动,如果必须要动的话,变成上一个位置上的数就可以了。这里假设上一个位置的数已经确定。
所以一个数要么是自己,要么是上一个位置上的数。而上一个数怎么来的呢?很明显,也是这样,要么不动,要么是上上个位置的数。可以一直推下去。这就口胡得出了众题解中的结论了:
存在一种最优方案,每个位置上的数,是原序列中的数。
下面由单增举例:
我们设
为了转移方便,我们处理一个b数组,为a数组排序后的数,
于是得出转移方程:
下面只贴单增的代码 (虽然也可以过Q^Q
#include<bits/stdc++.h>
using namespace std;
const int amou=2101,Inf=0x3f3f3f3f;
int a[amou],b[amou],n;
int f[amou][amou],Min[amou][amou];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
for(int i=1;i<=n;i++)
{
Min[i][0]=Inf;
for(int j=1;j<=n;j++)
{
f[i][j]=Min[i-1][j]+abs(a[i]-b[j]);
Min[i][j]=min(Min[i][j-1],f[i][j]);
}
}
printf("%d",Min[n][n]);
return 0;
}