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;
    }
    
  • 相关阅读:
    Android开发四大组件--Activity详解
    <base target="_blank"/>
    MVC EF异常-“序列化类型为 XX 的对象时检测到循环引用”
    错误:[将截断字符串或二进制数据。 语句已终止。]
    EasyUI queryParams属性 在请求远程数据同时给action方法传参
    存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。
    easyui DateTimeBox 取值
    [转载]再次谈谈easyui datagrid 的数据加载
    EasyUI datagrid 改变url属性 实现动态加载数据
    在js中获取easyui datagrid的数据
  • 原文地址:https://www.cnblogs.com/santiego/p/11798939.html
Copyright © 2011-2022 走看看