• 变形最短路


    http://poj.org/problem?id=3635

    有没有感觉神似 ACMER的出行计划

    我们知道dijkstra是贪心策略的dp嘛,贪心的是距离

    然而有时除了距离还有别的限制,在这里是油。这时候花费最小不一定是最优,还要考虑剩余的油

    dp(i,j)表示到i点时剩余j油时最少的花费

    在一个点可以选择向下走(油够的情况)或者加1份油(多次加一份油就相当于加任意份油)

    按照这样的dp策略就可以ac

    然后关于排重两种写法

    一种是无脑入队,出队的时候查重

    if(vis[u][oil])
         continue;
    vis[u][oil] = 1;

    还有一种是在入队之前看一下是否重复

    加油的 if(!vis[u][oil+1])
    和
    走路的if(!vis[v][oil-w])

    都能ac,不过居然是第一种快一些。。。

    暂时不知道为什么。。。【心碎】

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using std::priority_queue;
    const int maxn = 1e3+7, maxm = 1e4+7, size = 107, INF = 0x3f3f3f3f;
    struct edge{
        int v, w, nxt;
        edge(){}
        edge(int v, int w, int nxt):v(v), w(w), nxt(nxt){}
    }e[2*maxm];
    int head[maxn], next[maxn], cur, mny[maxn], n, m, vol;
    int vis[maxn][size], dp[maxn][size];
    struct state{
        int u, cost, oil;
        state(){}
        state(int u, int cost, int oil):u(u), cost(cost), oil(oil){}
        bool operator < (const state& tmp)const{
            return cost > tmp.cost;
        }
    };
    void addedge(int u, int v, int w){
        e[cur] = edge(v, w, head[u]);
        head[u] = cur++;
    }
    void dijkstra(int st, int ed){
        memset(dp, INF, sizeof(dp));
        memset(vis, 0, sizeof(vis));
        priority_queue<state>Q;
        Q.push(state(st, 0, 0));
        dp[st][0] = 0;
        while(!Q.empty()){
            state x = Q.top();
            Q.pop();
            int u = x.u, cost = x.cost, oil = x.oil;
            //printf("%d %d %d
    ", u, cost, oil);
            if(vis[u][oil])
                continue;
            vis[u][oil] = 1;
            if(u == ed){
                printf("%d
    ", cost);
                return;
            }
            if(oil+1 <= vol && dp[u][oil+1] > dp[u][oil] + mny[u]){
                dp[u][oil+1] = dp[u][oil] + mny[u];
                Q.push(state(u, dp[u][oil+1], oil+1));
            }
            for(int i = head[u]; ~i; i = e[i].nxt){
                int v = e[i].v, w = e[i].w;
                if(oil >= w && dp[v][oil-w] > cost){
                    dp[v][oil-w] = cost;
                    Q.push(state(v, dp[v][oil-w], oil-w));
                }
            }
        }
        puts("impossible");
    }
    int main(){
        memset(head, -1, sizeof(head));
        cur = 0;
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++)
            scanf("%d", &mny[i]);
        while(m--){
            int u, v, d;
            scanf("%d%d%d", &u, &v, &d);
            addedge(u, v, d);
            addedge(v, u, d);
        }
        int q;
        scanf("%d", &q);
        while(q--){
            int s, e;
            scanf("%d%d%d", &vol, &s, &e);
            dijkstra(s, e);
        }
        return 0;
    }
    搞图论是没有用的,转行做数学题了hh
  • 相关阅读:
    《大话数据结构》最小生成树——Prim算法
    《大话数据结构》图的BFS和DFS
    寒假集训日志(三)——数论
    寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路
    set
    寒假集训日志(一)——图,最短路问题
    经典的图论算法,C++描述
    动态数组
    stack and queue
    最长递增子序列,最长公共子串,最长公共子序列问题,最长公共增长子序列问题
  • 原文地址:https://www.cnblogs.com/DearDongchen/p/7525757.html
Copyright © 2020-2023  润新知