[USACO08FEB]修路Making the Grade
Posted excellent-zzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[USACO08FEB]修路Making the Grade相关的知识,希望对你有一定的参考价值。
给个n <= 2000长度数列,可以把每个数改为另一个数代价是两数之差的绝对值。求把它改为单调不增or不减序列最小代价。
把高度离散之后DP。。。存在b数组中b[j]表示第j大的高度。
我们用f[i][j]将前i段变作不下降序列,且第j段道路的高度为b[j]时的最小花费,显而易见,
f[i][j] = min(f[i - 1][k]) + abs(a[i] - b[j])(1<=k<=j)其中a[i]表示第i段路原本的高度。
枚举k的话,你会发现时间复杂度为n^3。为了解决这个问题,我们发现min(f[i - 1][k])是可以在做第i - 1段路段的时候处理出来的,所以复杂度就成了n ^ 2。
#define B cout << "BreakPoint" << endl; #define O(x) cout << #x << " " << x << endl; #define O_(x) cout << #x << " " << x << " "; #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl; #include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<stack> #define LL long long #define inf 1000000009 #define N 2019 using namespace std; int n,m,c[N][N],f[N][N],a[N],b[N],t[N],ans; inline int read() int s = 0,w = 1; char ch = getchar(); while(ch < ‘0‘ || ch > ‘9‘) if(ch == ‘-‘) w = -1; ch = getchar(); while(ch >= ‘0‘ && ch <= ‘9‘) s = s * 10 + ch - ‘0‘; ch = getchar(); return s * w; void ini() for (int i = 0; i <= n; i++) for (int j = 0; j <= m; j++) c[i][j] = f[i][j] = 0; return ; void dp() for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) f[i][j] = c[i - 1][j] + abs(a[i] - b[j]); if (j != 1) c[i][j] = min(c[i][j - 1],f[i][j]); else c[i][j] = f[i][j]; return ; void init() n = read(); for(int i = 1; i <= n; i++) a[i] = read(); t[i] = a[i]; return ; void solve() sort(t + 1,t + 1 + n); int res = -1; for(int i = 1; i <= n; i++) if(res != t[i]) b[++m] = t[i]; res = t[i]; ini(); dp(); ans = c[n][m]; for(int i = 1; i <= m / 2; i++) swap(b[i],b[m - i + 1]); ini(); dp(); ans = min(ans,c[n][m]); printf("%d",ans); return ; int main() init(); solve(); return 0;
以上是关于[USACO08FEB]修路Making the Grade的主要内容,如果未能解决你的问题,请参考以下文章
[USACO08FEB]修路Making the Grade
[USACO08FEB]Making the Grade G 和 CF714E
[USACO08FEB]Making the Grade G 和 CF714E
bzoj1592 [Usaco2008 Feb]Making the Grade 路面修整