• bzoj2516 电梯


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2516

    【题解】

    状压dp。

    $f_{sta,i}$表示状态为sta,当前在第i层的最小花费时间。状态是个三进制表示,0代表没进过电梯;1代表在电梯里;2表示进过电梯,出来了。

    然后考虑当前状态转移出去即可。复杂度$O(Cas * 3^n * nm)$,成功垫底。

    据说用2个二进制可以更快(逃

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    const int mod = 1e9+7, inf = 1e9;
    const int STATUS_SIZE = 59049 + 5;
    
    int n, m, fir, bin[12];
    int f[STATUS_SIZE][22], s[12];
    struct pa {
        int t, a, b;
        pa() {}
        pa(int t, int a, int b) : t(t), a(a), b(b) {}
    }p[12];
    
    vector<int> ps;
    
    # define abs(x) ((x) > 0 ? (x) : -(x))
    # define bit(x, i) (((x) / bin[i]) % 3)
    # define dist(i, j) (abs(ps[j-1] - ps[i-1]))
    
    inline int getid(int x) {
        return lower_bound(ps.begin(), ps.end(), x) - ps.begin() + 1;
    }
    
    inline void gmin(int &a, int b) {
        if(b < a) a = b;
    }
    
    
    inline void sol() {
        cin >> n >> fir;
        ps.clear(); ps.push_back(fir);
        for (int i=1; i<=n; ++i) {
            scanf("%d%d%d", &p[i].t, &p[i].a, &p[i].b);
            ps.push_back(p[i].a);
            ps.push_back(p[i].b);
        }
        sort(ps.begin(), ps.end());
        ps.erase(unique(ps.begin(), ps.end()), ps.end());
        for (int i=1; i<=n; ++i) {
            p[i].a = getid(p[i].a);
            p[i].b = getid(p[i].b);
        }
        fir = getid(fir); m = ps.size();
        for (int sta=0; sta<bin[n]; ++sta) for (int i=1; i<=m; ++i) f[sta][i] = inf;
        for (int i=1; i<=m; ++i) f[0][i] = dist(i, fir);
        for (int sta=0; sta<bin[n]; ++sta) {
            for (int i=1; i<=m; ++i) {
                for (int j=1; j<=n; ++j) {
                    if(bit(sta, j-1) == 1) gmin(f[sta+bin[j-1]][p[j].b], max(f[sta][i] + dist(p[j].b, i), p[j].t));
                    else if(bit(sta, j-1) == 0) gmin(f[sta+bin[j-1]][p[j].a], max(f[sta][i] + dist(p[j].a, i), p[j].t));
                }
            }
        }
        int ans = inf;
        for (int i=1; i<=m; ++i) gmin(ans, f[bin[n]-1][i]);
        cout << ans << endl;    
    }
    
    int main() {
        bin[0] = 1; for (int i=1; i<=10; ++i) bin[i] = bin[i-1]*3;
        int T; cin >> T;
        while(T--) sol();
        return 0;
    }
    View Code

     

  • 相关阅读:
    DevC++实现调试功能
    DevC++实现调试功能
    《算法竞赛入门经典》计算组合数问题
    C#根据控件名获取控件对象
    C#根据控件名获取控件对象
    C# 使用反射获取私有属性的方法
    C# 使用反射获取私有属性的方法
    JSON转Object的方式
    JSON转Object的方式
    Hadoop: Setting up a Single Node Cluster.
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2516.html
Copyright © 2020-2023  润新知