• poj3666 线性dp


    要把一个序列变成一个不严格的单调序列,求最小费用

    /*
    首先可以证明最优解序列中的所有值都能在原序列中找到 
    以不严格单增序列为例, 
    a序列为原序列,b序列为升序排序后的序列 
    dp[i][j]表示处理到a中第i个数,这些数中最大值为b[j]的费用,由单调性可知第i个数肯定变为b[j]
    那么dp[i][j]等价于第i个数变成b[j]的费用 
    那么有 dp[i][j]=abs(b[j]-a[i])+min(dp[i-1][k]),k<=j 
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm> 
    using namespace std;
    #define maxn 2005
    #define ll long long 
    ll n,a[maxn],b[maxn],dp[maxn][maxn]; 
    
    ll solveup(){
        sort(b,b+n);
        memset(dp,0,sizeof dp);
        for(int i=0;i<n;i++)
            dp[0][i]=abs(a[0]-b[i]);//初始条件 
            
        for(int i=1;i<n;i++){
            ll Min=dp[i-1][0];
            for(int j=0;j<n;j++){
                Min=min(Min,dp[i-1][j]);//单调增加的集合可以直接用Min来维护 
                dp[i][j]=abs(a[i]-b[j])+Min; 
            }
        }    
        
        ll ans=dp[n-1][0];//求结果 
        for(int i=1;i<n;i++)
            ans=min(ans,dp[n-1][i]);
        return ans;     
    }
    
    int main(){
        while(scanf("%lld",&n)==1){
            for(int i=0;i<n;i++)scanf("%lld",&a[i]),b[i]=a[i];
            printf("%lld
    ",solveup());
        }
    }

    可以用滚动数组实现,空间省了许多

    /*
    滚动数组解法,第一维可以省去,dp[j]表示已经完成的序列用的最大值是b[j],状态i会覆盖状态i-1并且没有影响 
    dp[j]=abs(a[i]-b[j])+min(dp[k]),k<=j 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 2005
    #define ll long long 
    
    ll n,a[maxn],b[maxn],dp[maxn];
    ll solve(){
        sort(b,b+n);
        for(int j=0;j<n;j++)
            dp[j]=abs(a[0]-b[j]);
        
        for(int i=1;i<n;i++){
            ll Min=dp[0];
            for(int j=0;j<n;j++){
                Min=min(Min,dp[j]);
                dp[j]=abs(a[i]-b[j])+Min;
            }
        }
        
        ll ans=dp[0];
        for(int j=1;j<n;j++) ans=min(ans,dp[j]);    
        return ans;
    } 
    
    int main(){
        while(scanf("%lld",&n)==1){
            for(int i=0;i<n;i++)scanf("%lld",&a[i]),b[i]=a[i];
            printf("%lld
    ",solve());
        }
    } 
  • 相关阅读:
    Google的Protobuf安装及使用笔记一
    std::list与std::map的排序比较
    svn库镜像
    daemontools中supervise系统进程监控
    memcached的客户端
    Memcached安装及使用
    eclipse下maven配置
    栈溢出
    堆排序
    redis使用笔记
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10213890.html
Copyright © 2020-2023  润新知