• E


    E - Help Jimmy

     POJ - 1661 

    这个题目本身不是很难,但是可以更加优化这个写法。

    开始是n*n

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <map>
    #include <string>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3 + 10;
    int dp[maxn][2];
    struct node {
        int l, r, h;
        node(int x = 0, int y = 0, int h = 0) :l(x), r(y), h(h) {}
    }ex[maxn];
    
    bool cmp(node a, node b) {
        return a.h > b.h;
    }
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            int n, x, y, maxs, ans = inf, flag = 0;
            memset(dp, inf, sizeof(dp));
            scanf("%d%d%d%d", &n, &x, &y, &maxs);
            for (int i = 1; i <= n; i++) {
                int a, b, w;
                scanf("%d%d%d", &a, &b, &w);
                if (a > b) swap(a, b);
                ex[i] = node(a, b, w);
            }
            sort(ex + 1, ex + 1 + n, cmp);
            for (int i = 1; i <= n; i++) {
                if (ex[i].l <= x && ex[i].r >= x && ex[i].h <= y) {
                    flag = 1;
                    dp[i][0] = y - ex[i].h + abs(ex[i].l - x);
                    dp[i][1] = y - ex[i].h + abs(ex[i].r - x);
                    // printf("l=%d r=%d
    ", ex[i].l, ex[i].r);
                    // printf("dp[%d]=%d dp[%d]=%d %d
    ", i, dp[i][0], i, dp[i][1], ex[i].h);
                    break;
                }
            }
            if (flag == 0 && y <= maxs) {
                printf("%d
    ", y);
                continue;
            }
            for (int i = 1; i <= n; i++) {
                int flag1 = 0, flag2 = 0;
                if (dp[i][0] >= inf || dp[i][1] >= inf) continue;
                for (int j = 1; j <= n; j++) {
                    if (i == j) continue;
                    if (ex[j].h > ex[i].h) continue;
                    int h = ex[i].h - ex[j].h;
                    if (h > maxs) continue;
    
                    if (ex[i].l <= ex[j].r&&ex[i].l >= ex[j].l&&flag1 == 0) {
                        flag1 = 1;
                        dp[j][0] = min(dp[j][0], dp[i][0] + abs(ex[i].l - ex[j].l) + h);
                        dp[j][1] = min(dp[j][1], dp[i][0] + abs(ex[i].l - ex[j].r) + h);
                        // printf("l=%d l=%d h=%d
    ", ex[i].l, ex[j].l, h);
                        // printf("ww dp[%d][0]=%d dp[%d][1]=%d %d
    ", j, dp[j][0], j, dp[j][1], ex[j].h);
                    }
    
                    if (ex[i].r <= ex[j].r&&ex[i].r >= ex[j].l&&flag2 == 0) {
                        flag2 = 1;
                        dp[j][0] = min(dp[j][0], dp[i][1] + abs(ex[i].r - ex[j].l) + h);
                        dp[j][1] = min(dp[j][1], dp[i][1] + abs(ex[i].r - ex[j].r) + h);
                        // printf("zz dp[%d][0]=%d dp[%d][1]=%d %d
    ", j, dp[j][0], j, dp[j][1], ex[j].h);
                    }
    
                }
                if (flag1 == 0 && ex[i].h <= maxs) ans = min(ans, dp[i][0] + ex[i].h);
                if (flag2 == 0 && ex[i].h <= maxs) ans = min(ans, dp[i][1] + ex[i].h);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    不把起点和终点当成平台的n*n
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <map>
    #include <string>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3 + 10;
    int dp[maxn][2];
    struct node {
        int l, r, h;
        node(int x = 0, int y = 0, int h = 0) :l(x), r(y), h(h) {}
    }ex[maxn];
    
    bool cmp(node a,node b)
    {
        return a.h > b.h;
    }
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            int n, x, y, maxs, ans = inf;
            memset(dp, inf, sizeof(dp));
            scanf("%d%d%d%d", &n, &x, &y, &maxs);
            for (int i = 1; i <= n; i++) {
                int a, b, w;
                scanf("%d%d%d", &a, &b, &w);
                if (w >= y) continue;
                if (a > b) swap(a, b);
                ex[i] = node(a, b, w);
            }
            ex[++n] = node(x, x, y);
            ex[++n] = node(-inf, inf, 0);
            sort(ex + 1, ex + 1 + n, cmp);
            dp[1][0] = 0, dp[1][1] = 0;
            for (int i = 1; i <= n; i++) {
                int flag1 = 0, flag2 = 0;
                if (dp[i][0] >= inf || dp[i][1] >= inf) continue;
                for (int j = i+1; j <= n; j++) {
                    if (ex[j].h >= ex[i].h) continue;
                    int h = ex[i].h - ex[j].h;
                    if (h > maxs) continue;
                    
                    if (ex[i].l <= ex[j].r&&ex[i].l >= ex[j].l&&flag1 == 0) {
                        flag1 = 1;
                        int val1 = abs(ex[i].l - ex[j].l);
                        int val2 = abs(ex[i].l - ex[j].r);
                        if (i == n || j == n) val1 = val2 = 0;
                        dp[j][0] = min(dp[j][0], dp[i][0] + val1 + h);
                        dp[j][1] = min(dp[j][1], dp[i][0] + val2 + h);
                        // printf("l=%d l=%d h=%d
    ", ex[i].l, ex[j].l, h);
                        // printf("ww dp[%d][0]=%d dp[%d][1]=%d %d
    ", j, dp[j][0], j, dp[j][1], ex[j].h);
                    }
    
                    if (ex[i].r <= ex[j].r&&ex[i].r >= ex[j].l&&flag2 == 0) {
                        flag2 = 1;
                        int val1 = abs(ex[i].r - ex[j].l);
                        int val2 = abs(ex[i].r - ex[j].r);
                        if (i == n || j == n) val1 = val2 = 0;
                        dp[j][0] = min(dp[j][0], dp[i][1] + val1 + h);
                        dp[j][1] = min(dp[j][1], dp[i][1] + val2 + h);
                        // printf("zz dp[%d][0]=%d dp[%d][1]=%d %d
    ", j, dp[j][0], j, dp[j][1], ex[j].h);
                    }
    
                }
            }
            printf("%d
    ", min(dp[n][0],dp[n][1]));
        }
        return 0;
    }
    把起点和终点当成平台的n*n

    然后这个题目可以用线段树优化成 n*logn+n 的复杂度。

    这个是因为每一个平台会落到的平台是固定的,所以可以用线段树预处理出来每一个平台的下一个平台。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <iostream>
    #include <map>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int M = 2e4 + 10;
    const int maxn = 2e3 + 10;
    struct node
    {
        int id, l, r, lx, rx, y;
        node(int id=0,int l=0,int r=0,int lx=0,int rx=0,int y=0):id(id),l(l),r(r),lx(lx),rx(rx),y(y){}
    }ex[maxn];
    int p[maxn];
    ll dp[maxn][2];
    bool cmp(int a,int b)
    {
        return ex[a].y < ex[b].y;
    }
    bool cmp1(int a, int b) {
        return ex[a].y > ex[b].y;
    }
    int sum[M * 8], lazy[M * 8];
    
    void build(int id,int l,int r)
    {
        sum[id] = lazy[id] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
    }
    
    void push_down(int id)
    {
        if (lazy[id] == 0) return;
        sum[id << 1] = lazy[id];
        sum[id << 1 | 1] = lazy[id];
        lazy[id << 1] = lazy[id << 1 | 1] = lazy[id];
        lazy[id] = 0;
    }
    
    void update(int id,int l,int r,int x,int y,int val)
    {
        // printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
        if(x<=l&&y>=r)
        {
            lazy[id] = val;
            sum[id] = val;
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, l, mid, x, y, val);
        if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val);
    }
    
    int query(int id,int l,int r,int pos)
    {
        if (l == r) return sum[id];
        int mid = (l + r) >> 1;
        push_down(id);
        if (pos <= mid) return query(id << 1, l, mid, pos);
        return query(id << 1 | 1, mid + 1, r, pos);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--)
        {
            memset(dp, inf, sizeof(dp));
            int N, X, Y, H;
            scanf("%d%d%d%d", &N, &X, &Y, &H);
            X += M;
            for(int i=1;i<=N;i++)
            {
                p[i] = i;
                int l, r, h;
                scanf("%d%d%d", &l, &r, &h);
                l += M, r += M;
                ex[i] = node(i, l, r, 0, 0, h);
            }
            N++;
            p[N] = N;
            ex[N] = node(0, -inf, inf, 0, 0, 0);
            build(1, 1, M * 2);
            sort(p + 1, p + 1 + N, cmp);
            for(int i=1;i<=N;i++)
            {
                // printf("i=%d p=%d
    ", i, p[i]);
                int l = ex[p[i]].l, r = ex[p[i]].r, id = ex[p[i]].id;
                ex[p[i]].lx = query(1, 1, M*2, l);
                ex[p[i]].rx = query(1, 1, M*2, r);
                // printf("l=%d r=%d
    ", l, r);
                // printf("ex[%d] lx=%d rx=%d
    ", p[i], ex[p[i]].lx, ex[p[i]].rx);
                update(1, 1, M*2, l, r, id);
            }
            int num = query(1, 1, M*2, X);
            if(num==0)
            {
                printf("%d
    ", Y);
                continue;
            }
            dp[num][0] = Y - ex[num].y + abs(X - ex[num].l);
            dp[num][1] = Y - ex[num].y + abs(X - ex[num].r);
            // printf("num=%d
    ", num);
            // printf("dp[%d][0]=%lld dp[%d][1]=%lld
    
    ", num, dp[num][0], num, dp[num][1]);
            sort(p + 1, p + 1 + N, cmp1);
            for(int i=1;i<=N;i++)
            {
                int id = ex[p[i]].id;
                // printf("p[%d]=%d id=%d
    ", i, p[i], id);
                if (dp[id][0] >= inf) continue;
                int lx = ex[id].lx;
                int rx = ex[id].rx;
                if(ex[id].y-ex[lx].y<=H)
                {
                    int val = abs(ex[id].l - ex[lx].l);
                    if (lx == 0) val = 0;
                    dp[lx][0] = min(dp[lx][0], dp[id][0] + ex[id].y - ex[lx].y + val);
                    val = abs(ex[id].l - ex[lx].r);
                    if (lx == 0) val = 0;
                    dp[lx][1] = min(dp[lx][1], dp[id][0] + ex[id].y - ex[lx].y + val);
                }
                if(ex[id].y-ex[rx].y<=H)
                {
                    int val = abs(ex[id].r - ex[rx].l);
                    if (rx == 0) val = 0;
                    dp[rx][0] = min(dp[rx][0], dp[id][1] + ex[id].y - ex[rx].y + val);
                    val = abs(ex[id].r - ex[rx].r);
                    if (rx == 0) val = 0;
                    dp[rx][1] = min(dp[rx][1], dp[id][1] + ex[id].y - ex[rx].y + val);
                }
                // printf("dp[%d][0]=%lld dp[%d][1]=%lld
    ", lx, dp[lx][0], lx, dp[lx][1]);
                // printf("dp[%d][0]=%lld dp[%d][1]=%lld
    
    ", rx, dp[rx][0], rx, dp[rx][1]);
            }
            printf("%lld
    ", min(dp[0][0], dp[0][1]));
        }
        return 0;
    }
    线段树 n*logn+n

    还应该可以直接把dp放到线段树里面,就只有n*logn的复杂度。

    这个暂时不想写了。

  • 相关阅读:
    数列(矩阵乘法+快速幂)
    最大公约数和最小公倍数问题
    解的个数(扩展欧几里得解不定方程)
    冒泡排序图(最长上升子序列变式)
    tomcat结合nginx使用小结
    ant构建web项目build脚本
    git分支合并到master
    oracle 存储过程,存储函数以及定时器的综合使用
    JPA 注解
    log4j简单应用
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11385909.html
Copyright © 2020-2023  润新知