标签:read line tchar 绝对值 int 处理 个数 making string
给个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
标签:read line tchar 绝对值 int 处理 个数 making string
原文地址:https://www.cnblogs.com/excellent-zzy/p/10991999.html