zoukankan      html  css  js  c++  java
  • [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;
    }
    

      

  • 相关阅读:
    kvm介绍
    正式班D24
    正式班D23
    正式班D21
    正式班D20
    正式班D19
    正式班D18
    正式班D17
    正式班D16
    正式班D15
  • 原文地址:https://www.cnblogs.com/excellent-zzy/p/10991999.html
Copyright © 2011-2022 走看看