POJ3666(动态规划)

题目:

C - Making the Grade
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
Appoint description: 

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



题意  :把一列数编程非严格单调序列所需要的最小花费。

思路:代码只求了了非递减序列的情况,但也能过。另一半同理。a为原始数列,b为排序过的数列。设dp[i][j]为把前i+1个数变成单调序列且最大为B[j]的最小花费。可以由哪些状态转移过来?

显然从dp[i-1][k]转移过来的时候,要使最大的为B[j],就只要把a[i]改成b[j]就成。所以dp[i][j]=min(dp[i-1][k])+abs(a[i]-b[j])


<span style="font-size:14px;">#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <cmath>

#define MAXN 2010
using namespace std;
int a[MAXN],b[MAXN];
int dp[MAXN][MAXN];//dp[i][j]为前把前i+1个数变为单调序列且最大数是B[j],此时的最小成本
//dp[i][j]=min(dp[i-1][k])+|a[i]-b[j]|

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",a+i);
        b[i]=a[i];
    }
    sort(b, b+n);
    for(int j=0;j<n;j++)
        dp[0][j]=abs((double)(a[0]-b[j]));
    for(int i=1;i<n;i++)
    {
        int minn=dp[i-1][0];
        for(int j=0;j<n;j++)
        {
            minn=min(minn,dp[i-1][j]);
            dp[i][j]=minn+abs((double)(a[i]-b[j]));
        }
    }
    printf("%d\n",*min_element(dp[n-1], dp[n-1]+n));
    return 0;
}</span>














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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值