zoukankan      html  css  js  c++  java
  • 汽车加油行驶

    试题描述
    给定一个 N×N的方形网格,设其左上角为起点◎,坐标为 (1,1),X 轴向右为正, Y 轴向下为正,每个方格边长为 1 ,如图所示。
    一辆汽车从起点◎出发驶向右下角终点▲,其坐标为 (N,N) 。
    在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守如下规则:
    汽车只能沿网格边行驶,装满油后能行驶 K 条网格边。出发时汽车已装满油,在起 点与终点处不设油库。

    汽车经过一条网格边时,若其 X 坐标或 Y 坐标减小,则应付费用 B ,否则免付费用。

    汽车在行驶过程中遇油库则应加满油并付加油费用 A。在需要时可在网格点处增设油库,并付增设油库费用 C (不含加油费用 A )。N,K,A,B,C 均为正整数, 且满足约束: 2≤N≤100,2≤K≤10

    设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。

    输入
    文件的第一行是 N,K,A,B,C 的值。
    第二行起是一个N∗N的 0-1 方阵,每行 N 个值,至 N+1 行结束。
    方阵的第 i 行第 j 列处的值为 1 表示在网格交叉点 (i,j) 处设置了一个油库,为 0 时表示未设油库。各行相邻两个数以空格分隔。
    输出
    程序运行结束时,输出最小费用。
    输入示例
    9 3 2 3 6
    0 0 0 0 1 0 0 0 0
    0 0 0 1 0 1 1 0 0
    1 0 1 0 0 0 0 1 0
    0 0 0 0 0 1 0 0 1
    1 0 0 1 0 0 1 0 0
    0 1 0 0 0 0 0 1 0
    0 0 0 0 1 0 0 0 1
    1 0 0 1 0 0 0 1 0
    0 1 0 0 0 0 0 0 0
    输出示例
    12
    其他说明
    数据范围与提示
    2≤n≤100
    2≤k≤10

     是一道网络流的模板题,然而并不会写,只好退而求其次,写一个SPFA+分层图

    听说还可以用BFS+优化过,也不知道是哪位高人

    板子就没什么好说的了

    唯一要注意的是dis[i][j][k]代表的是当汽车走到(x,y)时,所剩油量为k的最小花费

    还有分类讨论

    当还有油时

           如果下一个点是加油站,就直接过去

           如果不是

                   如果油够,就过去

                   不够,就建一个加油站

    没有油了,就建一个加油站再过去

    下面给出代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    using namespace std;
    inline int rd()
    {
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    void write(int x)
    {
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int n,k,a,b,c;
    int map[106][106];
    int dis[106][106][12],book[106][106][12];
    struct node
    {
        int x,y,v;
    };
    queue <node> q;
    void gt(int h1,int h2,int h3)
    {
        node hh;
        hh.x=h1;
        hh.y=h2;
        hh.v=h3;
        q.push(hh);
    }
    int dx[5]={0,0,1,0,-1},dy[5]={0,1,0,-1,0};//控制方向 
    int co[5];
    void inq(int x,int y,int v,int cos) 
    {
        if(dis[x][y][v]>cos)//比较是否更优 
        {
            dis[x][y][v]=cos;
            if(!book[x][y][v])//如果还没去过,就标记,然后进队 
            {
                book[x][y][v]=1;
                gt(x,y,v);
            }
        }
        return ;
    }
    void spfa()//SPFA模板 
    {
        dis[1][1][k]=0;
        gt(1,1,k);
        while(!q.empty())
        {
            node now=q.front();
            q.pop();
            book[now.x][now.y][now.v]=0;
            for(int i=1;i<=4;i++)
            {
                int xx=now.x+dx[i];
                int yy=now.y+dy[i];
                int cos=dis[now.x][now.y][now.v]+co[i];
                if(xx<=0||xx>n||yy<=0||yy>n) continue;
                if(now.v!=0)
                {
                    if(map[xx][yy]) inq(xx,yy,k,cos+a);
                    else
                    {
                        inq(xx,yy,now.v-1,cos);
                        inq(xx,yy,k-1,cos+c+a);
                    }
                }
                else inq(xx,yy,k-1,cos+a+c);
            }
        }
        return ;
    }
    int main()
    {
        n=rd();
        k=rd();
        a=rd();
        b=rd();
        c=rd();
        co[3]=co[4]=b;
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=rd();
        memset(dis,127,sizeof(dis));
        spfa();
        int ans=999999999;
        for(int i=0;i<=k;i++) ans=min(ans,dis[n][n][i]);//在到达终点的所剩所有用的情况中选最优,因为不一定省得油少就好 
        write(ans);
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?
    图解 Redis | 差点崩溃了,还好有主从复制
    图解 Redis | 不多说了,这就是 RDB 快照
    图解 Redis | 不就是 AOF 持久化嘛
    看书的一点小建议!
    图解高性能网络架构:Reactor 和 Proactor
    面试官:什么是死锁?怎么排查死锁?怎么避免死锁?
    HTTP/1.1 有点慢,我想优化下!
    Linux 内核和 Windows 内核有什么区别?
    提高代码颜值的几个小技巧
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9621636.html
Copyright © 2011-2022 走看看