题解 P2893 【[USACO08FEB]Making the Grade G】
其实这边题解的思路和楼上基本差不多
但是看到还可以提交
那怎么能不交呢
并且hack掉了楼上某一篇题解中的hack
希望能为大家带来一些新的思考
首先这道题数据比较水,只需要考虑单调不降的情况即可但事实上单调不增和单调不降其实是一样的,只需要改变一下递推顺序即可。
首先考虑贪心,我们考虑把每一个路的海拔提升至上一个路海拔。例如
9
5 5 5 1 1 1 5 5 5
则只需要将中间的三个1升高到5,总花费为12
但是,这种做法是非常好卡掉的,看下面这组数据
5
1000000000 0 0 0 1000000000
如果按照上面的贪心思想答案应为
贪心解决不了的问题,一般是动态规划。——rxz
那么我们来考虑动态规划,容易想到状态
我们看到j的范围高达
接下来考虑转移,很显然的是
这样复杂度为O(n^3),不能接受。下面考虑优化。
我们发现,每一次我们都花费了
则答案应为
最后注意边界条件与数组初始化就可以了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2010;
int n;
int a[maxn],b[maxn];
int f[maxn][maxn],mn[maxn][maxn];
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+n+1);
memset(mn,0x7f,sizeof(mn));
memset(mn[0],0,sizeof(mn[0]));
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
f[i][j] = mn[i-1][j] + abs(a[i]-b[j]);
mn[i][j] = min(mn[i][j-1],f[i][j]);
}
}
for(int i=2;i<=n;++i) f[n][i]=min(f[n][i],f[n][i-1]);
printf("%d",f[n][n]);
return 0;
}