zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Lombok Pojo默认初始值问题
    spring boot打包以及centos下部署
    Spring事件监听ApplicationListener源码流程分析
    synchronized是什么,用法及原理
    Spring动态切换数据源及事务
    linux环境中关闭tomcat,通过shutdown.sh无法彻底关闭--线程池
    LVS之DR模式
    LVS之ipvsadm命令
    LVS之NAT模式
    tcpdump抓包命令
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7101441.html
Copyright © 2011-2022 走看看