zoukankan      html  css  js  c++  java
  • CodeForces 13C【DP】

    题意:
    给你n个数,每次只能让一个数+1,或者-1,目标是最终使这个序列构成一个非递减的序列;
    n是5e3,复杂度n^2内。值是1e9;
    思路:
    可以发现子结构是保证一个区间的非递减,
    如果只是dp[a][b]代表在[a,b]上需要的最小步数,这样很难处理a,b位置的值,且不构成递推性;
    所以可以在递推中(前i个)去dp以 j 值为末端的区间需要的最小步数。
    dp[i][j]=min(dp[i][j],min(dp[i][k]+cost); //k∈[1-j];
    然而j值是1e9,且特么n是5e3都好大啊;如果小点就好做了。

    看了题解上面的方法可以离散化搞一搞,可是好麻烦。
    有一个结论:变化后的每一个值肯定是等于原来序列的某个值。

    那么变化后我们知道是非递减的,所以问题就转变为a数组变成b数组求一个最小花费;
    dp[i][j]为a序列前i个以b[j]结尾的b序列的最小花费

    #include<cstdio>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    
    const int N=5e3+10;
    
    int a[N];
    int b[N];
    LL dp[N];
    
    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);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)
            {
                dp[j]+=abs(a[i]-b[j]);
                if(j)
                    dp[j]=min(dp[j-1],dp[j]);
            }
        }
        printf("%I64d
    ",dp[n-1]);
        return 0;
    }
  • 相关阅读:
    WPF笔记(1)
    Java笔记(3)
    Java笔记(2)
    Java笔记(1)
    PHP学习笔记(5)
    PHP学习笔记(4)
    PHP学习笔记(3)
    PHP学习笔记(2)
    PHP学习笔记(1)
    WKWebView 支持https请求
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934852.html
Copyright © 2011-2022 走看看