zoukankan      html  css  js  c++  java
  • UVA LA 3983

    题目

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1984


    题意

    按顺序给出平面n个点,每个点上都有重物,一次只能按顺序拿重量不超过c的重物,从原点出发并且返回原点,问至少多少次能把全部重物拿回原点

    思路

    明显,令dp[i]为从1拿到i所需的最小出发次数,令dist0[i]为从原点到i的距离,令dist[i]为从i到i-1的距离(点0不妨设置为原点),令distSum[i] = sum(dist[0]...dist[i]),则dp[j] = dp[j] + dist0[j] + distSum[j] + dp[i] + dist0[i + 1] - distSum[i+1],此处j > i且i+1...j的重物重量和不超过c。设mycost[i] = dp[i] + dist0[i + 1] - distSum[i+1],明显,可以使用尺取+优先队列来维护重量和不超过c和 dp[i] + dist0[i + 1] - distSum[i+1]最小这两个条件。

    但刘书提出了进一步优化:由于当新加入的点i的mycost比尺取区间中维护的旧点小的时候,这些旧点是没有用的,可以不考虑它们。当这样做了之后,剩下的点总能成为一个递增序列,这样就非常容易维护。

    感想

    一开始DP公式推错了,弄成了还从该点出发

    代码

    #include <algorithm>
    #include <cassert>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <string>
    #include <tuple>
    #define LOCAL_DEBUG
    using namespace std;
    typedef pair<int, int> MyPair;
    const int MAXN = 1e5 + 5;
    int n, c;
    int x[MAXN];
    int y[MAXN];
    int w[MAXN];
    int wSum[MAXN];
    int distSum[MAXN];
    int dist0[MAXN];
    int dp[MAXN];
    int mydeque[MAXN];
    int mycost[MAXN];
    
    #define MYCOST(x) (dist0[(x) + 1] - distSum[(x) + 1] + dp[(x)])
    
    int main() {
    #ifdef LOCAL_DEBUG
        freopen("C:\Users\Iris\source\repos\ACM\ACM\input.txt", "r", stdin);
        //freopen("C:\Users\Iris\source\repos\ACM\ACM\output.txt", "w", stdout);
    #endif // LOCAL_DEBUG
        int T;
        scanf("%d", &T);
        for (int ti = 1; ti <= T && scanf("%d%d", &c, &n) == 2; ti++) {
            for (int i = 1; i <= n; i++) {
                scanf("%d%d%d", x + i, y + i, w + i);
                dist0[i] = abs(x[i]) + abs(y[i]);
            }
            for (int i = 1; i <= n; i++) {
                wSum[i] = w[i] + wSum[i - 1];
                distSum[i] = abs(x[i] - x[i - 1]) + abs(y[i] - y[i - 1]);
                distSum[i] += distSum[i - 1];
            }
    
            int dequeTop = 0;
            int dequeEnd = 0;
            mydeque[dequeEnd++] = 0;
            for (int i = 1; i <= n; i++) {
                while (dequeTop < dequeEnd && wSum[i] - wSum[mydeque[dequeTop]] > c) {
                    dequeTop++;
                }
                assert(dequeTop < dequeEnd);
                int f = mydeque[dequeTop];
                dp[i] = dist0[i] + dist0[f + 1] + distSum[i] - distSum[f + 1] + dp[f];
                while (dequeTop < dequeEnd && MYCOST(mydeque[dequeEnd - 1]) >= MYCOST(i)) {
                    dequeEnd--;
                }
                mydeque[dequeEnd++] = i;
            }
            if (ti != 1)puts("");
            printf("%d
    ", dp[n]);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    mysqldump备份数据库时排除某些库
    Dataguard后台进程解析
    mysql 查看所有存储过程
    Oracle 中的 TO_DATE 和 TO_CHAR 函数
    trunc的使用
    mysql now() sysdate() curdate()区别
    ORA-10456:cannot open standby database;media recovery session may be in process
    ORACLE 修改日志大小及增加日志成员
    Oracle 11gR2用gpnp profile存放ASM的spfile路径
    C语言malloc()函数:动态分配内存空间
  • 原文地址:https://www.cnblogs.com/xuesu/p/10457160.html
Copyright © 2011-2022 走看看