• [CF1340C] Nastya and Unexpected Guest


    [CF1340C] Nastya and Unexpected Guest - DFS

    Description

    现在有一条长度为n的街道,你要从0走到n,每个单位时间走一格,每格都有一个红绿灯。你只能朝一个方向并且每个单位时间一定要走一格,但是现在有m个岗亭,你到了岗亭时可以选择是否转向,并且在绿灯最后一秒的时候你一定要在某一个岗亭。问你最少要花多少时间到目的地。(n le 10^6, m le 10^4, g le 10^3)

    Solution

    我们把一个绿灯周期称为一个阶段,那么我们一定是要先优化阶段数,再优化阶段内的时间

    阶段 stage,当前处在的点 p,阶段内的剩余时间 t,我们用 (s,p,t) 来描述一个状态

    如果 (i,p,t) 有对应的 (j,p,t) 出现过,满足 (j<i),那么 (i,p,t) 不可能贡献最优解

    所以我们分阶段搜索,每段的结束状态扔到后一阶段的起始状态,每段内部做记忆化 DFS

    总体复杂度为 O(mg),因为每个状态只会刷一次

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 10005;
    const int M = 1005;
    int vis[N][M], pos[N], n, m, r, g, ans = 1e18;
    vector<int> f[N];
    void dfs(int stage, int p, int t)
    {
        if (p < 1 || p > m)
            return;
        if (t < 0)
            return;
        if (vis[p][t])
            return;
        vis[p][t] = 1;
        if (p == m)
            ans = min(ans, stage * (g + r) + g - t);
        if (t > 0)
        {
            dfs(stage, p + 1, t - pos[p + 1] + pos[p]);
            dfs(stage, p - 1, t - pos[p] + pos[p - 1]);
        }
        else
        {
            f[stage + 1].push_back(p);
        }
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
            cin >> pos[i];
        cin >> g >> r;
        sort(pos + 1, pos + m + 1);
        f[0].push_back(1);
        for (int i = 0; i < m; i++)
            for (int p : f[i])
                dfs(i, p, g);
        cout << (ans < 1e16 ? ans : -1) << endl;
    }
    
    
    
  • 相关阅读:
    C版程序语法 (消除左递归)
    文法
    201506110248 实验报告
    组合数据类型
    UBUNTU四种版本的区别【转】
    MFC对话框程序屏蔽回车与ESC键,Tab键
    std::fstream打开中文路径名失败的问题原因、解决方法以及注意事项
    前进。。。。。。
    程序员学习能力提升三要素[转]
    java学习推荐资源
  • 原文地址:https://www.cnblogs.com/mollnn/p/14568785.html
Copyright © 2020-2023  润新知