描述:
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 6357 | Accepted: 2958 |
Description
A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ would like to add and remove dirt from the road so that it becomes one monotonic slope (either sloping up or down).
You are given N integers A1, ... , AN (1 ≤ N ≤ 2,000) describing the elevation (0 ≤ Ai ≤ 1,000,000,000) at each of N equally-spaced positions along the road, starting at the first field and ending at the other. FJ would like to adjust these elevations to a new sequence B1, . ... , BN that is either nonincreasing or nondecreasing. Since it costs the same amount of money to add or remove dirt at any position along the road, the total cost of modifying the road is
| A 1 - B 1| + | A 2 - B 2| + ... + | AN - BN |
Please compute the minimum cost of grading his road so it becomes a continuous slope. FJ happily informs you that signed 32-bit integers can certainly be used to compute the answer.
Input
* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains a single integer elevation: Ai
Output
* Line 1: A single integer that is the minimum cost for FJ to grade his dirt road so it becomes nonincreasing or nondecreasing in elevation.
Sample Input
7 1 3 2 4 5 3 9
Sample Output
3
Source
题意:
给一个序列,可以给每一个数加减一个数,代价为他们改变的数的绝对值,那么要求用最小代价把序列变成单调非增或者单调非减的(但是这题数据有bug,只需要求单调非减就行)n<=1e3
cf上有一个取自这题的严格单增的版本:CF 714 E 题解见Here
思路:
很容易想到是DP
dp[i][j]表示前i个数以j为结尾的非减序列的最小代价,当然这个j需要离散化
dp[i]][j]=abs(a[i]-j)+dp[i-1][k] (k<=j ) :即从i-1个序列的最优方案里选一个转移
有三个变量 i j k看起来是三重循环,其实里面有重复计算
我们分析一下
很显然k是满足k<=j的,那么也就是当要计算dp[i][j]时,必须要知道dp[i-1][1...j]的最小值,
而dp[i-1][1...j]肯定在计算dp[i][1...j]之前就已经计算过了,那么我们记录一下他们的最小值mn即可
dp[i]][j]=abs(a[i]-j)+mn
复杂度n * j的范围
然后就是离散化j,显然,j选择原序列的数就是最好的了,因为如果选了一个其他的值得到最优值,那么必然可以通过转换,使得最终序列花费不变,并全部用原序列的数。(算贪心吧)
这样子 i是1-n,j是a[1..n]的枚举
复杂度就是O(n^2)
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll __int64
using namespace std;
const int N=2005;
int n,a[N],b[N];
ll dp[N][N];
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
void solve(){
for(int i=1; i<=n; i++){
ll mn=dp[i-1][1];
for(int j=1; j<=n; j++){
mn=min(mn, dp[i-1][j]);
dp[i][j]=abs(a[i]-b[j])+mn;
}
}
ll ans=dp[n][1];
for(int i=2; i<=n; i++){
ans=min(ans, dp[n][i]);
}
printf("%I64d\n",ans);
}
int main(){
read(n);
for(int i=1; i<=n; i++){
read(a[i]);
b[i]=a[i];
}
sort(b+1, b+n+1);
solve();
return 0;
}

本文介绍了一道经典的算法题目——POJ3666 MakingtheGrade,通过动态规划的方法解决如何调整一条道路上的海拔高度,使其形成单一斜坡的问题。给出了解题思路和步骤,并提供了完整的代码实现。

1523

被折叠的 条评论
为什么被折叠?



