• hdu4362 dp + 单调队列优化


    dp传输方程很easy需要 dp[i][j] = min{dp[i - 1][k] + abs(pos[i][j] -pos[i - 1][j]) + cost[i][j]}

    n行m一排 每个传输扫描m二级 干脆n*m*m 至O(10^7)    1500ms,能够暴力一试。姿势不正确就会TLE

    事实上加上个内联函数求绝对值,同一时候赋值时候不使用min(a, b)  用G++交 就能够水过


    正解是:由于每一个转移都是从上一层全部的状态開始转移。将上一层的状态依据pos排序

    对当前状态的pos进行讨论,其坐标轴左边的点dp[i][j] = dp[i - 1][k] - pos][i - 1][k]+ pos[i][j]  + cost[i][j]

              对其坐标轴右边的点便是 dp[i][j] = dp[i - 1][k]+ pos][i - 1][k]  - pos[i][j] + cost[i][j]。       pos][i][j] cost[i][j]是常数。

     维护一个lans[i],表示上一层0 ~ i位置的dp[i - 1][k] - pos][i - 1][k]最小值。   和一个rans[i],表示上一层i ~ (m - 1)位置的dp[i - 1][k] + pos][i - 1][k]最小值

    二分当前状态的pos,若为p。比較左边lans[p - 1]与右边lans[p]的最小值就可以


    //#pragma comment(linker, "/STACK:102400000,102400000")
    //HEAD
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    #include <queue>
    #include <string>
    #include <set>
    #include <stack>
    #include <map>
    #include <cmath>
    #include <cstdlib>
    
    using namespace std;
    //LOOP
    #define FE(i, a, b) for(int i = (a); i <= (b); ++i)
    #define FED(i, b, a) for(int i = (b); i>= (a); --i)
    #define REP(i, N) for(int i = 0; i < (N); ++i)
    #define CLR(A,value) memset(A,value,sizeof(A))
    //STL
    #define PB push_back
    //INPUT
    #define RI(n) scanf("%d", &n)
    #define RII(n, m) scanf("%d%d", &n, &m)
    #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
    #define RS(s) scanf("%s", s)
    
    #define FF(i, a, b) for(int i = (a); i < (b); ++i)
    #define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
    #define CPY(a, b) memcpy(a, b, sizeof(a))
    #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
    #define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
    #define ALL(c) (c).begin(), (c).end()
    #define SZ(V) (int)V.size()
    #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
    #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
    #define WI(n) printf("%d
    ", n)
    #define WS(s) printf("%s
    ", s)
    #define sqr(x) x * x
    typedef long long LL;
    typedef vector <int> VI;
    typedef unsigned long long ULL;
    const double eps = 1e-10;
    const LL MOD = 1e9 + 7;
    
    using namespace std;
    
    const int maxn = 1010;
    const int INF = 0x3f3f3f3f;
    
    int dp[55][maxn], n, m, x;
    int lm[maxn], rm[maxn], lans[maxn], rans[maxn];
    
    struct Node{
        int pos, cost;
        int lval, rval;
        bool operator <(const Node& a) const
        {
            return pos < a.pos;
        }
    }a[55][maxn];
    
    void init(int u)
    {
    
        REP(j, m)
        {
            a[u][j].lval = dp[u][j] - a[u][j].pos;
            a[u][j].rval = dp[u][j] + a[u][j].pos;
        }
        sort(a[u], a[u] + m);
        CLR(lm, INF), CLR(rm, INF);
        int s = 0, e = 0;
        lans[0] = lm[0] = a[u][0].lval, rans[m - 1] = rm[0] = a[u][m - 1].rval;
        FF(j, 1, m)
        {
            Node &v = a[u][j];
            if (v.lval > lm[e])   lm[++e] = v.lval;
            else
            {
                while (e >= 0 && v.lval < lm[e])  --e;
                lm[++e] = v.lval;
            }
            lans[j] = lm[0];
        }
        s = e = 0;
        FED(j, m - 2, 0)
        {
            Node &v = a[u][j];
            if (v.rval > rm[e])   rm[++e] = v.rval;
            else
            {
                while (e >= 0 && v.rval < rm[e])  --e;
                rm[++e] = v.rval;
            }
            rans[j] = rm[0];
        }
    }
    
    int main()
    {
        int T;
        RI(T);
        while (T--)
        {
            RIII(n, m, x);
            REP(i, n)   REP(j, m)   RI(a[i][j].pos);
            REP(i, n)   REP(j, m)   RI(a[i][j].cost);
            REP(j, m)   dp[0][j] = abs(x - a[0][j].pos) + a[0][j].cost;
            FE(i, 1, n - 1)
            {
                init(i - 1);
                REP(j, m)
                {
                    int p = lower_bound(a[i - 1], a[i - 1] + m, a[i][j]) - a[i - 1];
    //                cout << "position  "<< p << endl;
                    int lmin = INF, rmin = INF;
                    if (p) lmin = lans[p - 1] + a[i][j].pos + a[i][j].cost;
                    if (p < m)  rmin = rans[p] - a[i][j].pos + a[i][j].cost;
    //                cout << "rans[p]:  " << rans[p] << endl;
    //                cout << "lmin: " <<lmin << "rmin:  " << rmin << endl;
                    dp[i][j] = min(lmin, rmin);
                }
            }
            int ans = INF;
            REP(j, m)   ans = min(dp[n - 1][j], ans);
            cout << ans << endl;
        }
        return 0;
    }
    

    这是水过的 1109ms

    //#pragma comment(linker, "/STACK:102400000,102400000")
    //HEAD
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    #include <queue>
    #include <string>
    #include <set>
    #include <stack>
    #include <map>
    #include <cmath>
    #include <cstdlib>
    
    using namespace std;
    //LOOP
    #define FE(i, a, b) for(int i = (a); i <= (b); ++i)
    #define FED(i, b, a) for(int i = (b); i>= (a); --i)
    #define REP(i, N) for(int i = 0; i < (N); ++i)
    #define CLR(A,value) memset(A,value,sizeof(A))
    //STL
    #define PB push_back
    //INPUT
    #define RI(n) scanf("%d", &n)
    #define RII(n, m) scanf("%d%d", &n, &m)
    #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
    #define RS(s) scanf("%s", s)
    
    #define FF(i, a, b) for(int i = (a); i < (b); ++i)
    #define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
    #define CPY(a, b) memcpy(a, b, sizeof(a))
    #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
    #define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
    #define ALL(c) (c).begin(), (c).end()
    #define SZ(V) (int)V.size()
    #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
    #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
    #define WI(n) printf("%d
    ", n)
    #define WS(s) printf("%s
    ", s)
    #define sqr(x) x * x
    typedef long long LL;
    typedef vector <int> VI;
    typedef unsigned long long ULL;
    const double eps = 1e-10;
    const LL MOD = 1e9 + 7;
    
    using namespace std;
    
    const int maxn = 1010;
    const int INF = 0x3f3f3f3f;
    
    inline int ABS(int x)   {if (x < 0) return -x; return x; }
    int pos[55][maxn], cost[55][maxn];
    int dp[55][maxn];
    
    int main()
    {
        int T, n, m, x;
        RI(T);
        while (T--)
        {
            RIII(n, m, x);
            REP(i, n)   REP(j, m)   RI(pos[i][j]);
            REP(i, n)   REP(j, m)   RI(cost[i][j]);
            REP(i, m)
                dp[0][i] = ABS(x - pos[0][i]) + cost[0][i];
            FE(i, 1, n - 1)
                REP(j, m)
                {
                    int t = INF;
                      REP(k, m)
                    {
    //                    dp[i][j] = min(dp[i][j], dp[i - 1][k] + ABS(pos[i][j] - pos[i - 1][k]));
                        int x = dp[i - 1][k] + ABS(pos[i][j] - pos[i - 1][k]);
                        if (x < t)
                            t = x;
                    }
                    dp[i][j] = t + cost[i][j];
                }
            int ans = INF;
            REP(i, m)   ans = min(ans, dp[n - 1][i]);
            WI(ans);
        }
        return 0;
    }


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    安装插件 YouCompleteMe 成功却无法自动补全C++的解决办法
    Ubuntu 16.04 使用 vim_plug 安装插件 YouCompleteMe 报错“ycmd server SHUT DOWN”
    POJ #1062 昂贵的聘礼 有限制的最短路 枚举+dijkstra求最短路
    POJ #3259 Wormholes 判负环 SPFA
    POJ #1860 Currency Exchange 最短路径算法 Bellman-ford SPFA 判断负环
    spfa 算法模板 可求带负权边的最短路 判断负环
    POJ #1042 Gone Fishing 贪心
    路人甲
    Perface
    1. Perface
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4837472.html
Copyright © 2020-2023  润新知