【网络流24题】汽车加油行驶(分层图+最短路)

20 篇文章 0 订阅
9 篇文章 0 订阅

传送门

    汽车加油行驶
    题意:给定网格,部分格点设有加油站,汽车驶至该格点必须加油。给定一辆车加满油的最大行驶距离,加一次油的花费,以及在任意点设置新油库的花费。求一辆满油车从左上角格点到右下角格点的最小花费。

I think

    根据汽车的剩余油量建立分层图。
    若油量不满,点< i,k>向点< i,top>连长度为A/A+C的边。
    若油量非空,非油库点< i,k>向点< j,k-1>连长度为0的边(j为i在网格图中右/下方的相临点),向点< j,k-1>连长度为B的边(j为i在网格图中左/上方的相临点).而满油油库点< i,k>向点< j,k-1>连长度为0的边(j为i在网格图中右/下方的相临点),向点< j,k-1>连长度为B的边(j为i在网格图中左/上方的相临点).(非满油油库点必然加油).

Code

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

typedef pair<int,int> pii;

const int sm = 11e4+10;
const int sn = 10*sm;
const int Inf = 0x3f3f3f3f;

int N,K,A,B,C,tot,Ans;
int to[sn],nxt[sn],hd[sm],c[sn];
int vis[sm],dis[sm];
int mp[11][102][102];
int tag[102][102];

int Min(int x,int y) { return x<y?x:y; }
void Add(int u,int v,int w) {
    to[++tot]=v,nxt[tot]=hd[u],hd[u]=tot,c[tot]=w;
}
bool chk(int u,int v) {
    return (u>=1&&u<=N&&v>=1&&v<=N);
}
void Dijkstra(int s,int St) {
    for(int i=1;i<=s;++i) dis[i]=Inf;
    priority_queue<pii,vector<pii>,greater<pii> >Que;
    Que.push(make_pair(dis[St]=0,St));
    pii t; 
    while(!Que.empty()) {
        t=Que.top(),Que.pop();
        if(vis[t.second])continue;
        vis[t.second]=1;
        for(int i=hd[t.second];i;i=nxt[i])
            if(!vis[to[i]]&&dis[to[i]]>dis[t.second]+c[i]) {
                dis[to[i]]=dis[t.second]+c[i];
                Que.push(make_pair(dis[to[i]],to[i]));
            }
    } 
}
int main() {
    int cnt=0,u;
    scanf("%d%d%d%d%d",&N,&K,&A,&B,&C);
    for(int k=0;k<=K;++k)
        for(int i=1;i<=N;++i)
            for(int j=1;j<=N;++j) {
                if(k==0) scanf("%d",&tag[i][j]);//tag[i][j]==1该点设置了油库
                mp[k][i][j]=++cnt;
            }

    for(int k=K;k>=0;--k)
        for(int i=1;i<=N;++i)
            for(int j=1;j<=N;++j) {
                if(k!=K) //油量不满
                    Add(mp[k][i][j],mp[K][i][j],A+C*(tag[i][j]^1));
                if((!tag[i][j]&&k>0)||(k==K)) { //油量非空 //是油库且非满油 必然加油
                    if(chk(i,j+1)) Add(mp[k][i][j],mp[k-1][i][j+1],0);
                    if(chk(i+1,j)) Add(mp[k][i][j],mp[k-1][i+1][j],0);
                    if(chk(i,j-1)) Add(mp[k][i][j],mp[k-1][i][j-1],B);
                    if(chk(i-1,j)) Add(mp[k][i][j],mp[k-1][i-1][j],B);
                }

            }
    Dijkstra(cnt,mp[K][1][1]);
    Ans=Inf;
    for(int i=0;i<=K;++i)
        Ans=Min(Ans,dis[mp[i][N][N]]);
    printf("%d\n",Ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.问题描述 给定一个N*N 的方形网格,设其左上角为起点,坐标为(1,1),X 轴向右为正,Y 轴 向下为正,每个方格边长为1。一辆汽车从起点出发驶向右下角终点,其坐标为(N,N)。 在若干个网格交叉点处,设置了油库,可供汽车行驶途中加油汽车行驶过程中应遵守 如下规则: (1)汽车只能沿网格边行驶,装满油后能行驶K 条网格边。出发时汽车已装满油,在 起点与终点处不设油库。 (2)当汽车行驶经过一条网格边时,若其X 坐标或Y 坐标减小,则应付费用B,否则 免付费用。 (3)汽车行驶过程中遇油库则应加满油并付加油费用A。 (4)在需要时可在网格点处增设油库,并付增设油库费用C(不含加油费用A)。 (5)(1)~(4)中的各数N、K、A、B、C均为正整数。 算法设计: 求汽车从起点出发到达终点的一条所付费用最少的行驶路线。 数据输入: 输入数据。第一行是N,K,A,B,C的值,2 <= N <= 100, 2 <= K <= 10。第二行起是一个N*N 的0-1方阵,每行N 个值,至N+1行结束。方阵的第i 行第j 列处的值为1 表示在网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。 各行相邻的2 个数以空格分隔。 结果输出: 将找到的最优行驶路线所需的费用,即最小费用输出. Sample input 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 Sample output 12

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值