码迷,mamicode.com
首页 > 其他好文 > 详细

Making the Grade---poj3666(dp)

时间:2016-08-19 11:14:52      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://poj.org/problem?id=3666

题意:有一个n个数的序列a,现在要把这些序列变成单调增的或者单调减的序列 b ,

其价值为|AB1| + |AB2| + ... + |AN - BN | 现在要让价值最小;

b序列表示为 a 的有序序列;

用dp[i][j]表示把前i - 1个数变成单调且最后一个数是b[j]的最小价值;

那么dp[i][j] = min(dp[i-1][k]) + abs(a[i]-b[j]);(1<= k <= j);

看似三层循环,但是求最小值的可以省略;

k<=j是因为,前i-1个数已经变成单调的了,要想第i个数也是单挑的,那么前i个数就要小于等于b[j];

 

题的数据可能比较水,只需求变成单挑递增的即可,否则还要倒着来一遍;

技术分享
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<math.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2100
#define PI 4*atan(1.0)
#define mod 110119
#define met(a, b) memset(a, b, sizeof(a))
typedef long long LL;

int a[N], b[N], dp[N][N], n;

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

        met(dp, 0);

        for(int i=1; i<=n; i++)
        {
            int Min = INF;
            for(int j=1; j<=n; j++)
            {
                Min = min(dp[i-1][j], Min);
                dp[i][j] = Min + abs(a[i]-b[j]);
            }
        }
        int ans = INF;
        for(int i=1; i<=n; i++)
            ans = min(ans, dp[n][i]);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

Making the Grade---poj3666(dp)

标签:

原文地址:http://www.cnblogs.com/zhengguiping--9876/p/5786825.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!