当前位置: 首页 > article >正文

[分层图] 汽车加油行驶问题

题目描述

给定一个 N × N N \times N N×N 的方形网格,设其左上角为起点◎,坐标为 ( 1 , 1 ) (1, 1) (1,1) X X X 轴向右为正, Y Y Y 轴向下为正,每个方格边长为 1 1 1,如图所示。

一辆汽车从起点◎出发驶向右下角终点▲,其坐标为 ( N , N ) (N, N) (N,N)

在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。

汽车在行驶过程中应遵守如下规则:

  1. 汽车只能沿网格边行驶,装满油后能行驶 K K K 条网格边。出发时汽车已装满油,在起点与终点处不设油库。
  2. 汽车经过一条网格边时,若其 X X X 坐标或 Y Y Y 坐标减小,则应付费用 B B B,否则免付费用。
  3. 汽车在行驶过程中遇油库则应加满油并付加油费用 A A A
  4. 在需要时可在网格点处增设油库,并付增设油库费用 C C C(不含加油费用 A A A)。
  5. N , K , A , B , C N, K, A, B, C N,K,A,B,C 均为正整数,且满足约束 2 ≤ N ≤ 100 , 2 ≤ K ≤ 10 2 \le N \le 100, 2 \le K \le 10 2N100,2K10

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

在这里插入图片描述

输入格式

第一行包含五个整数 N , K , A , B , C N, K, A, B, C N,K,A,B,C

第二行起是一个 N × N N \times N N×N 0 − 1 0-1 01 方阵,每行 N N N 个值,至 N + 1 N + 1 N+1 行结束。

方阵的第 i i i 行第 j j j 列处的值为 1 1 1 表示在网格交叉点 ( i , j ) (i, j) (i,j) 处设置了一个油库,为 0 0 0 时表示未设油库。

各行相邻两个数以空格分隔。

输出格式

输出共一行,为最小费用。

样例

样例输入1:

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

样例输出1:

12

数据范围

2 ≤ N ≤ 100 2 \le N \le 100 2N100
2 ≤ K ≤ 10 2 \le K \le 10 2K10

题解

求最小花费,还有油量限制,考虑使用 dp 解决(分层图)。

( x , y ) (x, y) (x,y) 坐标油量为 k k k 看作一个点。

接下来考虑如何转移:

假如当前点 ( x , y , k ) (x, y, k) (x,y,k),首先可以消耗油量直接转移到旁边的四个点(注意向左或向上走要花费 B B B

if(i - 1 >= 0) v[t].push_back({get(i - 1, j, K - 1), B});
if(j - 1 >= 0) v[t].push_back({get(i, j - 1, K - 1), B});
if(i + 1 < n) v[t].push_back({get(i + 1, j, K - 1), 0});
if(j + 1 < n) v[t].push_back({get(i, j + 1, K - 1), 0});

若当前点是油库,则当前点的任意油量可以连到满油量。

for(int k = 0; k < K; ++ k){
    v[get(i, j, k)].push_back({t, A + C});
}

最后跑一遍最短路,求出最小花费。

int n, K, A, B, C;
vector<pair<int, int>> v[110010];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
int dis[110010];
int fl[110010];
int get(int x, int y, int k){
    return (x * n + y) * (K + 1) + k;
}
void dijkstra(int x){
    memset(dis, 0x3f, sizeof(dis));
    memset(fl, 0, sizeof(fl));
    dis[x] = 0;
    q.push({0, x});
    while(!q.empty()){
        auto t = q.top();
        q.pop();
        if(fl[t.second]) continue;
        fl[t.second] = 1;
        for(auto i : v[t.second]){
            if(dis[i.first] > dis[t.second] + i.second){
                dis[i.first] = dis[t.second] + i.second;
                q.push({dis[i.first], i.first});
            }
        }
    }
}
int main(){
    scanf("%d %d %d %d %d", &n, &K, &A, &B, &C);
    for(int i = 0; i < n; ++ i){
        for(int j = 0; j < n; ++ j){
            int x;
            scanf("%d", &x);
            if(x){
                int t = get(i, j, K);
                for(int k = 0; k < K; ++ k){
                    v[get(i, j, k)].push_back({t, A});
                }
                if(i - 1 >= 0) v[t].push_back({get(i - 1, j, K - 1), B});
                if(j - 1 >= 0) v[t].push_back({get(i, j - 1, K - 1), B});
                if(i + 1 < n) v[t].push_back({get(i + 1, j, K - 1), 0});
                if(j + 1 < n) v[t].push_back({get(i, j + 1, K - 1), 0});
            }
            else{
                int t = get(i, j, K);
                for(int k = 0; k < K; ++ k){
                    v[get(i, j, k)].push_back({t, A + C});
                }
                for(int k = 1; k <= K; ++ k){
                    int p = get(i, j, k);
                    if(i - 1 >= 0) v[p].push_back({get(i - 1, j, k - 1), B});
                    if(j - 1 >= 0) v[p].push_back({get(i, j - 1, k - 1), B});
                    if(i + 1 < n) v[p].push_back({get(i + 1, j, k - 1), 0});
                    if(j + 1 < n) v[p].push_back({get(i, j + 1, k - 1), 0});
                }
            }
        }
    }
    dijkstra(get(0, 0, K));
    int ans = 0x3f3f3f3f;
    for(int k = 0; k < K; ++ k){
        ans = min(ans, dis[get(n - 1, n - 1, k)]);
    }
    printf("%d", ans);
    return 0;
}

http://www.kler.cn/a/613590.html

相关文章:

  • WebGL图形编程实战【3】:矩阵操控 × 从二维到三维的跨越
  • AI 对话艺术:Prompt 设计技巧与案例解析
  • JAVA实现动态IP黑名单过滤
  • 21.(vue3.x+vite)使用scss
  • 【Flutter入门】1. 从零开始的flutter跨平台开发之旅(概述、环境搭建、第一个Flutter应用)
  • ES 加入高亮设置
  • 面向对象——开闭原则(Open-Closed Principle, OCP)
  • 大模型——AI驱动的README生成器 效率翻倍
  • 零基础驯服GitHub Pages
  • 调用deepseek大模型时智能嵌入函数
  • SpringAI与JBoltAI深度对比:从工具集到企业级AI开发范式的跃迁
  • UI产品经理基础(六):如何解决用户的质疑?
  • Unix/Linux 中 dup、dup2 和 dup3 系统调用解析
  • unity中Xcharts图表鼠标悬浮表现异常
  • Appium中元素定位之一个元素定位API
  • AIGC-头条号长文项目创作智能体完整指令(DeepSeek,豆包,千问,Kimi,GPT)
  • (!常识!)C++中的内存泄漏和野指针——如何产生?如何避免?解决方案?基本原理?面试常问重点内容?
  • 【后端】【Django】Django 信号(Signals)详解
  • 【动手学深度学习】#6 卷积神经网络
  • 鸿蒙北向应用开发:deveco 5.0 kit化文件相关