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<cstdio>
#include<iostream>
#include<algorithm>

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;
}


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值