zoukankan      html  css  js  c++  java
  • 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());
        }
    } 
  • 相关阅读:
    HttpClient POST/GET方法
    Selenium+Java(十一)Selenium窗口切换
    Selenium+Java(十)Selenium常用方法
    Selenium+Java(九)Selenium键盘与鼠标事件
    Selenium+Java(八)Selenium下拉框处理
    Selenium+Java(七)Selenium对话框的处理
    Selenium+Java(六)Selenium 强制等待、显式等待、隐实等待
    [java]对象创建的过程
    [正则表达式] 表达式使用记录
    【Mysql】主从复制
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10213890.html
Copyright © 2011-2022 走看看