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

题目描述

给定一个 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 2≤N≤100,2≤K≤10。

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

输入格式

第一行包含五个整数 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 0−1 方阵,每行 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 2≤N≤100
2 ≤ K ≤ 10 2 \le K \le 10 2≤K≤10

题解

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

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

接下来考虑如何转移:

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

cpp 复制代码
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});

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

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

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

cpp 复制代码
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;
}
相关推荐
Tech Synapse30 分钟前
基于Surprise和Flask构建个性化电影推荐系统:从算法到全栈实现
python·算法·flask·协同过滤算法
終不似少年遊*37 分钟前
国产之光DeepSeek架构理解与应用分析04
人工智能·python·深度学习·算法·大模型·ds
天天扭码37 分钟前
一分钟解决 | 高频面试算法题——最大子数组之和
前端·算法·面试
杰杰批42 分钟前
力扣热题100——矩阵
算法·leetcode·矩阵
明月看潮生1 小时前
青少年编程与数学 02-016 Python数据结构与算法 28课题、图像处理算法
图像处理·python·算法·青少年编程·编程与数学
_GR1 小时前
2025年蓝桥杯第十六届C&C++大学B组真题及代码
c语言·数据结构·c++·算法·贪心算法·蓝桥杯·动态规划
心想事“程”1 小时前
决策树详解+面试常见问题
算法·决策树·机器学习
照海19Gin2 小时前
数据结构中的宝藏秘籍之广义表
c语言·数据结构·算法
小oo呆3 小时前
【自然语言处理与大模型】模型压缩技术之剪枝
算法·机器学习·剪枝
bloxd yzh3 小时前
筛选法(埃氏筛法)C++
数据结构·算法