zoukankan      html  css  js  c++  java
  • D. Treasure Hunting ( 思维题 , 贪心)

    传送门

    题意: 在一个 n * m 的地图里,有 k 个宝藏,你的起点在 (1, 1), 每次你能 向下向右向左移动(只要在地图里);

           现在,有 q 个安全的列, 你只有在这些列上面,你才能向下走。 问你收集所有宝藏,需要走的最少步数

    解: 首先,我们对每一行 维护数组 L, R,分别代表 这一行的所有宝藏中,最左的那个和最右的那个的 纵坐标

      然后 维护两个值  ansl, ansr 分别代表你处理完前 i 行所有的宝藏都拿完了之后;

      停在 L[ i ], 和停在 R[ i ]处的最小步数;

      那么你更新 ansl, ansr 各有四种情况; ( 代码有提到,详见代码)

      然后处理完N行后, 去 ansl, ansr 较小的那个,就是所有横向需要走的最小步数。

      然后纵向的话,你走的步数就是 所有宝藏中最大的 x - 1 步;

      然后相加就是答案了。

    #include <iostream>
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    #include <cmath>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <map>
    #include <stack>
    #include <set>
    #define LL long long
    #define ULL unsigned long long
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define dep(i,j,k) for(int i=k;i>=j;i--)
    #define INF 0x3f3f3f3f3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define make(i,j) make_pair(i,j)
    #define pb push_back
    #define Pi acos(-1.0)
    using namespace std;
    const int N = 2e5 + 5;
    LL l[N], r[N], s[N];
    int main() {
        int n, m, k, q;
        while(~scanf("%d %d %d %d", &n, &m, &k, &q)) {
            rep(i, 1, n) l[i] = INF, r[i] = 0;
            LL Y = 0;
            rep(i, 1, k) {
                LL x, y;
                scanf("%lld %lld", &x, &y);
                Y = max(Y, x);
                l[x] = min(l[x], y);
                r[x] = max(r[x], y);
            }
            rep(i, 1, q) scanf("%lld", &s[i]);
            sort(s + 1, s + 1 + q);
            LL ansl, ansr;
            LL L = l[1], R = r[1];
            if(r[1] == 0) ansl = 0, ansr = 0, L = R = 1;
            else ansl = r[1] - 1 + r[1] - l[1], ansr = r[1] - 1;
            rep(i, 2, n) if(r[i]) {
    
                int indexl = lower_bound(s + 1, s + 1 + q, L) - s;
                int indexr = lower_bound(s + 1, s + 1 + q, R) - s;
    
                int Ll, Lr, Rl, Rr;  Ll = Lr = Rl = Rr = INF;
                if(indexl <= q) Lr = s[indexl]; if(indexl > 1) Ll = s[indexl - 1];
                if(indexr <= q) Rr = s[indexr]; if(indexr > 1) Rl = s[indexr - 1];
    
                LL nowL = INF, nowR = INF;
    
                nowL = min(nowL, ansl + abs(L - Ll) + abs(Ll - r[i]) + abs(r[i] - l[i])); ///L -> Ll -> r[i] -> l[i]
                nowL = min(nowL, ansl + abs(L - Lr) + abs(Lr - r[i]) + abs(r[i] - l[i])); ///L -> Lr -> r[i] -> l[i]
                nowL = min(nowL, ansr + abs(R - Rl) + abs(Rl - r[i]) + abs(r[i] - l[i])); ///R -> Rl -> r[i] -> l[i]
                nowL = min(nowL, ansr + abs(R - Rr) + abs(Rr - r[i]) + abs(r[i] - l[i])); ///R -> Rr -> r[i] -> l[i]
    
                nowR = min(nowR, ansl + abs(L - Ll) + abs(Ll - l[i]) + abs(l[i] - r[i])); ///L -> Ll -> l[i] -> r[i]
                nowR = min(nowR, ansl + abs(L - Lr) + abs(Lr - l[i]) + abs(l[i] - r[i])); ///L -> Lr -> l[i] -> r[i]
                nowR = min(nowR, ansr + abs(R - Rl) + abs(Rl - l[i]) + abs(l[i] - r[i])); ///R -> Rl -> l[i] -> r[i]
                nowR = min(nowR, ansr + abs(R - Rr) + abs(Rr - l[i]) + abs(l[i] - r[i])); ///R -> Rr -> l[i] -> r[i]
    
                ansl = nowL, ansr = nowR; L = l[i], R = r[i];
            }
            printf("%lld
    ", min(ansl, ansr) + Y - 1);
        }
        return 0;
    }
    View Code
    一步一步,永不停息
  • 相关阅读:
    Win10 蓝屏
    XE Button Color
    IOS 屏幕尺寸
    Delphi 转圈 原型进度条 AniIndicator 及线程配合使用
    Delphi 询问框 汉化
    Delphi Android 询问框
    Delphi BLE 控件
    浮点高低位赋值
    delphi 蓝牙 TBluetoothLE
    16进制字节转换
  • 原文地址:https://www.cnblogs.com/Willems/p/11303439.html
Copyright © 2011-2022 走看看