zoukankan      html  css  js  c++  java
  • 汽车加油行驶问题 分层图最短路

    汽车加油行驶问题 分层图最短路

    1. 汽车只能沿网格边行驶,装满油后能行驶 (K) 条网格边。出发时汽车已装满油,在起点与终点处不设油库。
    2. 汽车经过一条网格边时,若其 (X) 坐标或 (Y) 坐标减小,则应付费用 (B) ,否则免付费用。
    3. 汽车在行驶过程中遇油库则应加满油并付加油费用 (A)
    4. 在需要时可在网格点处增设油库,并付增设油库费用(C)(不含加油费用(A) )。

    (k+1)层图,表示汽车油量(k)的状态(油量(0cdots k)),然后根据具体规则在其上建图以转移状态。规定第(k)层(从(0)开始)第(i)行第(j)列点编号为(k*n*n+(i-1)*n+j),然后起点即为(k*n*n+1),新建一个超级终点,将每层图的(n*n)这个点建一条边权为(0)的边指向这个超级终点即可。

    跑最短路的过程相当于状态转移求解(DP)的过程。

    #include <cstdio>
    #include <queue>
    #include <cstring>
    using namespace std;
    #define MAXN 110*110
    #define MAXK 13
    #define MAXM MAXN*4
    inline int read(){
        char ch=getchar();int s=0;
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') s=s*10+(ch^'0'), ch=getchar();
        return s;
    }
    int head[MAXN*MAXK],nxt[MAXM*MAXK],vv[MAXM*MAXK],ww[MAXM*MAXK],tot;
    inline void add_edge(int u, int v, int w){
        vv[++tot]=v;
        ww[tot]=w;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    bool ins[MAXN*MAXK];
    int dis[MAXN*MAXK];
    queue <int> q;
    void spfa(int s){
        memset(dis, 0x3f, sizeof dis);
        memset(ins, 0, sizeof ins);
        while(!q.empty()) q.pop();
        dis[s]=0;
        q.push(s);
        while(!q.empty()){
            int u=q.front();q.pop();
            ins[u]=0;
            for(register int i=head[u];i;i=nxt[i]){
                int v=vv[i],w=ww[i];
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    if(!ins[v]) q.push(v),ins[v]=1;
                }
            }
        }
    }
    int n,k,cost_a,cost_b,cost_c;
    inline void add(int ux, int uy, int uz, int vx, int vy, int vz, int w){
        add_edge((ux-1)*n+uy+uz*n*n, (vx-1)*n+vy+vz*n*n, w);
    }
    int main(){
        n=read(),k=read(),cost_a=read(),cost_b=read(),cost_c=read();
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=n;++j){
                int rd=read();
                if(rd==0){
                    for(int t=0;t<k;++t) add(i, j, t, i, j, k, cost_a+cost_c);
                    for(int t=1;t<=k;++t){
                        if(i>=2) add(i, j, t, i-1, j, t-1, cost_b);
                        if(j>=2) add(i, j, t, i, j-1, t-1, cost_b);
                        if(i<=n-1) add(i, j, t, i+1, j, t-1, 0);
                        if(j<=n-1) add(i, j, t, i, j+1, t-1, 0);
                    }
                }else{
                    for(int t=0;t<k;++t) add(i, j, t, i, j, k, cost_a);
                  	// 有加油站的必须加满油,所以只在k层图上建边
                    if(i>=2) add(i, j, k, i-1, j, k-1, cost_b);
                    if(j>=2) add(i, j, k, i, j-1, k-1, cost_b);
                    if(i<=n-1) add(i, j, k, i+1, j, k-1, 0);
                    if(j<=n-1) add(i, j, k, i, j+1, k-1, 0);
                }
            }
        for(int i=0;i<=k;++i)
            add(n, n, i, 1, 1, k+1, 0); // 超级终点
        spfa(1+n*n*k);
        printf("%d", dis[1+n*n*(k+1)]);
        return 0;
    }
    
  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/santiego/p/11798939.html
Copyright © 2011-2022 走看看