POJ3666_Making the Grade_DP

Making the Grade
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6994   Accepted: 3234

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 B 1| + | A 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


一条土路上有n段,每一段的高度可能各不相同。现要求在一部分路上增加一些土或减少一些土,使这条路的高度变成 单调不减少 或 单调不增加。求改动的土的最小值。


/***********************************
DP题都做了十几条了,这个转移方程还是
没写出来,感觉自己真的好弱啊。。。

对于前i个数,我们需要关心的有两个值
1.把它变成单调序列需要的土,越少越好
2.第i个数的大小,越小越好

于是dp[i][j]表示考虑前i个数,第i个数
是j时,至少需要的土

第i个数是j时最少需要的土,就等于j和
a[i]差的绝对值+ 第i-1个数小于等于j时
至少需要土的最小值

即转移方程为:
dp[i][j]=abs(j-a[i])+min(dp[i-1][k])
k <= j

到这里问题就基本解决了。但是因为a[i]
的范围太大了,这样枚举k时就会TLE。这
里需要离散化优化

搞一个数组b,将a中的元素复制进去,然
后排序。
对于每个ij转移时,只要检查b中小于j的
元素就可以了

或者可以进一步省去遍历过程
对于dp[i-1][j],维护一个最小值
每次直接加最小值就可以了
***********************************/
#include
#include
#include

using namespace std;

const int maxn = 2010;
long long inf = 2147483646;
long long dp [maxn][maxn];
int a [maxn], b [maxn];
int n;

int main ()
{
	scanf("%d", &n);
	for(int i= 1; i<= n; i++){
		scanf("%d", a+i);
		b[i] = a[i];
	}
	sort(b+1, b+n+1);

	for(int i= 1; i<= n; i++){
		long long m = dp[i-1][1];

		for(int j= 1; j<= n; j++){
			m = min(m, dp[i-1][j]);
			dp[i][j] = abs(a[i] - b[j]) + m;
		}
	}

	long long ans = inf;
	for(int i= 1; i<= n; i++)
		ans = min(ans, dp[n][i]);

	printf("%lld\n", ans);

	return 0;
}


你可能感兴趣的:(DP)