• codeforces C. Sonya and Problem Wihtout a Legend(dp or 思维)


    题目链接:http://codeforces.com/contest/713/problem/C

    题解:这题也算是挺经典的题目了,这里附上3种解法优化程度层层递进,还有这里a[i]-i<=a[i+1]-(i+1),处理一下。

    首先是最基础的dp[i][j]前i位最大值为j的最小值为多少。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #define inf 0X3f3f3f3f
    using namespace std;
    const int M = 3e3 + 10;
    typedef long long ll;
    ll dp[M][M] , a[M] , b[M];
    int main() {
        int n;
        scanf("%d" , &n);
        memset(b , 0 , sizeof(b));
        for(int i = 1 ; i <= n ; i++) scanf("%lld" , &a[i]) , b[i] = a[i] = a[i] - i;
        memset(dp , inf , sizeof(dp));
        int cnt = 0;
        b[0] = -1000000000000000;
        sort(b + 1 , b + 1 + n);
        for(int i = 1 ; i <= n ; i++) {
            if(b[i] != b[i - 1]) b[++cnt] = b[i];
        }
        for(int i = 1 ; i <= cnt ; i++) dp[0][i] = 0;
        for(int i = 1 ; i <= n ; i++) {
            ll tmp = dp[i - 1][1];
            for(int j = 1 ; j <= cnt ; j++) {
                tmp = min(tmp , dp[i - 1][j]);
                dp[i][j] = tmp + abs(a[i] - b[j]);
            }
        }
        ll ans = 1000000000000000;
        for(int i = 1 ; i <= cnt ; i++) {
            ans = min(ans , dp[n][i]);
        }
        printf("%lld
    " , ans);
        return 0;
    }

    然后是滚动优化注意那个dp的转移方式只和上一个状态有关系所以可以用滚动优化dp[2][M],这样优化了空间

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define inf 0X3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int M = 3e3 + 10;
    int a[M] , b[M];
    ll dp[2][M];
    int main() {
        int n , m;
        scanf("%d" , &n);
        for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]) , a[i] -= i , b[i] = a[i];
        m = 0;
        sort(b + 1 , b + 1 + n);
        b[0] = -1e9 - 10;
        for(int i = 1 ; i <= n ; i++) {
            if(b[i] != b[i - 1]) b[++m] = b[i];
        }
        memset(dp , inf , sizeof(dp));
        for(int i = 1 ; i <= n ; i++) dp[0][i] = 0;
        for(int i = 1 ; i <= n ; i++) {
            ll tmp = dp[(i - 1) % 2][1];
            for(int j = 1 ; j <= m ; j++) {
                tmp = min(tmp , dp[(i - 1) % 2][j]);
                dp[i % 2][j] = tmp + abs(a[i] - b[j]);
            }
        }
        ll Min = 1e15 + 10;
        for(int i = 1 ; i <= m ; i++) Min = min(Min , dp[n % 2][i]);
        printf("%lld
    " , Min);
        return 0;
    }
    

    最后是最强的优化复杂度可以到达O(nlogn),就是用优先队列来优化,其实这个具体去证明也不太好证明但是理解还是好理解的具体画一下图意会一下

    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    priority_queue<int>q;
    int main() {
        int n;
        cin >> n;
        long long ans = 0;
        for(int i = 1 ; i <= n ; i++) {
            int x;
            scanf("%d" , &x);
            x -= i;
            q.push(x);
            if(q.top() > x) {
                int t = q.top();
                q.pop();
                ans += t - x;
                q.push(x);
            }
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    Hadoop学习笔记(九)HDFS架构分析
    Hadoop学习笔记(九)HDFS架构分析
    Hadoop学习笔记(八)MapReduce深入分析
    Hadoop学习笔记(八)MapReduce深入分析
    Hadoop学习笔记(七)
    Hadoop学习笔记(七)
    Hadoop学习笔记(六)启动Shell分析
    Hadoop学习笔记(六)启动Shell分析
    「2018-11-05模拟赛」T5 传送机 解题报告
    NOIP 2018 普及组 解题报告
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7101441.html
Copyright © 2020-2023  润新知