zoukankan      html  css  js  c++  java
  • AcWing:176. 装满的油箱(bfs + dijiskla思想)

    有N个城市(编号0、1…N-1)和M条道路,构成一张无向图。

    在每个城市里边都有一个加油站,不同的加油站的单位油价不一样。

    现在你需要回答不超过100个问题,在每个问题中,请计算出一架油箱容量为C的车子,从起点城市S开到终点城市E至少要花多少油钱?

    输入格式

    第一行包含两个整数N和M。

    第二行包含N个整数,代表N个城市的单位油价,第i个数即为第i个城市的油价pipi。

    接下来M行,每行包括三个整数u,v,d,表示城市u与城市v之间存在道路,且车子从u到v需要消耗的油量为d。

    接下来一行包含一个整数q,代表问题数量。

    接下来q行,每行包含三个整数C、S、E,分别表示车子油箱容量、起点城市S、终点城市E。

    输出格式

    对于每个问题,输出一个整数,表示所需的最少油钱。

    如果无法从起点城市开到终点城市,则输出”impossible”。

    每个结果占一行。

    数据范围

    1N10001≤N≤1000,
    1M100001≤M≤10000,
    1pi1001≤pi≤100,
    1d1001≤d≤100,
    1C1001≤C≤100

    输入样例:

    5 5
    10 10 20 12 13
    0 1 9
    0 2 8
    1 2 1
    1 3 11
    2 3 7
    2
    10 0 3
    20 1 4
    

    输出样例:

    170
    impossible

    算法:bfs + dijiskla思想

    题解:这题是用bfs + 优先队列来做,而且需要用到dijiskla的思想,那么我们可以用枚举法来做,首先从起点出发,先加一升油试一下,加一升油能到达的站点放入队列,因为队列是以花费钱来从小到大排序,所以我在把这个加了一升油的情况放入队列,如果这个加了一升油的情况还是花费最小的话,我就会继续加第二升油,如果不是的话,那么我就会用到其他的。到最后的时候,可能最开始第一个点的加一升油还没有用到,那是因为它并不是最优解,你思考一下,多加一升油的性价比就不高了,你还会去多加n升油吗,所以之后的解就都不是我们要找的最优解,之后就是重复我最开始所说的加一升油试一试这个思路。如果还是不够理解的话,可以看代码,代码上也有解释哟!

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <memory.h>
    
    using namespace std;
    
    const int maxn = 1e4+7;
    
    struct node {
        int u, f, w;
        friend bool operator < (node a, node b) {   //优先队列重载,权值小的排前面
            return a.w > b.w;
        }
    };
    
    vector<pair<int, int> > g[maxn];
    
    int n, m;
    int wn[maxn];
    int dp[maxn][105];
    int vis[maxn][105];
    int c, s, e;
    
    bool check1(int u, int f) { //判断是否能够在当前站点加一升油
        if(f + 1 <= c && !vis[u][f + 1] && dp[u][f + 1] > dp[u][f] + wn[u]) {   //如果能加一升油,并且加这升油一定比原来的那个好(原来的那个可能是初始化的INF,也可能是已经经过的这个地方时更新的值)
            return true;
        }
        return false;
    }
    
    bool check2(int f, int v, int p, int w) {   //判断下一个站点是否能走
        if(f >= p && !vis[v][f - p] && dp[v][f - p] > w) {  //如果当前油要大于需要花费的油,并且原来的费用比现在的要高(同理,可能是INF,也可能是更新过的值)
            return true;
        }
        return false;
    }
    
    int bfs() {
        priority_queue<node> q;
        memset(vis, 0, sizeof vis);
        memset(dp, 0x3f3f3f3f, sizeof dp);
        dp[s][0] = 0;
        q.push((node){s, 0, 0});
        while(!q.empty()) {
            node now = q.top();
            q.pop();
            int u = now.u;
            int f = now.f;
            int w = now.w;
            vis[u][f] = 1;
            if(u == e) {
                return w;
            }
            if(check1(u, f)) {      //先加一升油试一下
                dp[u][f + 1] = dp[u][f] + wn[u];
                q.push((node){u, f + 1, dp[u][f + 1]});
            }
            int len = g[u].size();
            for(int i = 0; i < len; i++) {
                int v = g[u][i].first;
                int p = g[u][i].second;
                if(check2(f, v, p, w)) {
                    dp[v][f - p] = w;
                    q.push((node){v, f - p, w});
                }
            }
        }
        return -1;  //无解
    }
    
    int main() {
        scanf("%d %d", &n, &m);
        for(int i = 0; i < n; i++) {
            scanf("%d", &wn[i]);
        }
        for(int i = 1; i <= m; i++) {
            int u, v, w;
            scanf("%d %d %d", &u, &v, &w);
            g[u].push_back(make_pair(v, w));
            g[v].push_back(make_pair(u, w));
        }
        int q;
        scanf("%d", &q);
        while(q--) {
            scanf("%d %d %d", &c, &s, &e);
            int ans = bfs();
            if(ans == -1) {
                printf("impossible
    ");
            } else {
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    淘宝网的质量属性的六个常见属性场景
    架构漫谈读书笔记
    软件架构师的工作流程
    centos7通过docker安装mysql
    centos7下安装docker
    VMware 虚拟机下CentOS 7连接网络
    在JSP中使用el函数标签获取默认值(男女性别选项)
    ssm登录与退出
    MVC(Model -View-Controller)实例应用模式
    MVC模式
  • 原文地址:https://www.cnblogs.com/buhuiflydepig/p/11367487.html
Copyright © 2011-2022 走看看