zoukankan      html  css  js  c++  java
  • USACO13NOV Pogo-Cow S

    题目链接

    Solution

    刚开始没看到向任意方向跳,惨遭 WA 54pts QWQ

    (f_{i,j}) 表示当前是 (i) 号节点,上一个从 (j) 处跳过来的最大价值。那么得到转移方程式:

    [f_{i,j}=max(f_{i,j},f_{j,k}+y_i) (x_j-x_k≤x_i-x_j) ]

    如果暴力枚举 (i,j,k),复杂度 (O(n^3)),很明显不能通过此题。考虑优化。设:

    [Max_{i,j}=max(f_{i,k}) (1≤k<j) ]

    相当于一个前缀最大值。那么这个数组怎么用呢?

    如果对 (x_i) 进行排序,那么对于 (f_{i,j}),如果它能从 (f_{j,k}) 转移过来,那它也能从 (f_{j,h} (h<k)) 转移过来。这时候我们只需把转移方程式变成:

    [f_{i,j}=max(f_{i,j},Max_{j,k}) ]

    其中 (k)距离 i 最近的可以到达的点。现在的问题变成了寻找 (k),在 ([0,j-1]) 范围内二分即可。

    注意: 还是开头那个问题,需要分别按照 (x_i) 从小到大和从大到小排序,dp 两遍才能得到答案。

    时间复杂度 (O(n^2log_n))

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define LL long long
    using namespace std;
    
    const int N = 2333;
    struct node { LL x, y; } a[N];
    LL n, ans = 0, f[N][N], Max[N][N];
    
    LL GetPos(LL x, LL y)
    {
        LL l = 0, r = x - 1;
        while(l + 1 < r)
        {
            LL mid = (l + r) >> 1;
            if(abs(a[x].x - a[mid].x) >= abs(a[y].x - a[x].x)) l = mid;
            else r = mid;
        }
        if(abs(a[x].x - a[r].x) >= abs(a[y].x - a[x].x)) return r;
        return l;
    }
    
    bool cmp1(node a, node b) { return a.x < b.x; }
    bool cmp2(node a, node b) { return a.x > b.x; }
    
    void dp()
    {
        memset(f, -0x7f7f7f, sizeof(f));
        a[0].x = -1e18, a[0].y = 0;
        f[0][0] = Max[0][0] = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 0; j < i; j++)
                f[i][j] = max(f[i][j], Max[j][GetPos(j, i)] + a[i].y);
            for(int j = 0; j < i; j++)
                Max[i][j] = max(Max[i][j - 1], f[i][j]);
        }
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < i; j++)
                ans = max(ans, f[i][j]);
        return ;
    }
    
    int main()
    {
        scanf("%lld", &n);
        memset(f, -0x7f7f7f, sizeof(f));
        memset(Max, -0x7f7f7f, sizeof(Max));
        for(int i = 1; i <= n; i++) scanf("%lld%lld", &a[i].x, &a[i].y);
        sort(a + 1, a + n + 1, cmp1), dp();
        sort(a + 1, a + n + 1, cmp2), dp();
        printf("%lld", ans);
        return 0;
    }
    
  • 相关阅读:
    UIActinSheet和UIActionSheetDelegate
    UIWebView和UIWebViewDelegate的基本用法
    iOS开发拓展篇—音效的播放
    【零基础学习iOS开发】【02-C语言】10-函数
    李洪强漫谈iOS开发[C语言-012]-C语言基本数据类型
    iOS开发拓展篇—UIDynamic(捕捉行为)
    【零基础学习iOS开发】【02-C语言】09-流程控制
    李洪强iOS开发拓展篇—UIDynamic(重力行为+碰撞检测)
    李洪强iOS开发之【零基础学习iOS开发】【02-C语言】08-基本运算
    LeetCode 153 Find Minimum in Rotated Sorted Array
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13813910.html
Copyright © 2011-2022 走看看