《算法竞赛进阶指南》0x51线性DP POJ3666分级

Posted randy-lo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛进阶指南》0x51线性DP POJ3666分级相关的知识,希望对你有一定的参考价值。

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

题目给出一个序列a,要求给出一个序列b使得两个数列每一项相减的绝对值之和最小,这里有一个重要的性质:存在一个满足条件的b,其中的数在a中都出现,可以通过数学归纳法去证明。

然后就是dp的转移,前i个数设定好,并且第i个数是第j大的a中的数,这时的转移方程是dp[i][j]=min{dp[i-1][k]}+abs(a[i]-a‘[j]),其中k属于[1,j]。

通过前缀最大值的思想容易优化成O(n^2)

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 2020;
int a[maxn],b[maxn];
int f[maxn][maxn];
const int inf=0x7fffffff;
int n;
int dp(){
    for(int i=1;i<=n;i++)b[i]=a[i];
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++){
        int minv=inf;
        for(int j=1;j<=n;j++){
            minv=min(minv,f[i-1][j]);
            f[i][j]=minv+abs(a[i]-b[j]);
        }
    }
    int res=inf;
    for(int i=1;i<=n;i++)res=min(res,f[n][i]);
    return res;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    int res=dp();
    reverse(a+1,a+n+1);
    res=min(res,dp());
    cout<<res<<endl;
}

 

以上是关于《算法竞赛进阶指南》0x51线性DP POJ3666分级的主要内容,如果未能解决你的问题,请参考以下文章

《算法竞赛进阶指南》0x51线性DP 照相馆排列

《算法竞赛进阶指南》0x51线性DP 传纸条

算法竞赛进阶指南扩展最大子段和POJ1050ToTheMax

《算法竞赛进阶指南》0x02 POJ2889 分形

《算法竞赛进阶指南》0x43线段树 扫描线算法 POJ2482

《算法竞赛进阶指南》0x27A* 八数码问题 POJ1077