[网络流24题]汽车加油行驶问题

时间:2019-03-26
本文章向大家介绍[网络流24题]汽车加油行驶问题,主要包括[网络流24题]汽车加油行驶问题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

分析

网络流24题总结

维护三个状态(x,y,k)表示当前坐标(x,y)和剩余流量k,dist(x,y,k)表示当前状态下的最小花费

到了每一个点分类讨论:

1.遇到油库,必须加满,以加满的状态继续转移

2.没有油库,设一个油库,并把油加满

3.没有油库,继续走

代码

最短路:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 105
#define maxk 15 
#define INF 0x3f3f3f3f
using namespace std;
int n,k,a,b,c;
int graph[maxn][maxn];
int dist[maxn][maxn][maxk];
int inq[maxn][maxn][maxk];
struct node{
    int x;
    int y;
    int k;
    node(){
        
    }
    node(int xpos,int ypos,int oil){
        x=xpos;
        y=ypos;
        k=oil;
    }
    void debug(){
        printf("(%d,%d) oil=%d money=%d\n",x,y,k,dist[x][y][k]);
    }
};
queue<node>q;
const int walkx[4]={1,-1,0,0},walky[4]={0,0,1,-1};
int spfa(){
    memset(dist,0x3f,sizeof(dist));
    dist[1][1][k]=0;
    inq[1][1][k]=1;
    q.push(node(1,1,k));
    while(!q.empty()){
        node now=q.front();
        q.pop();
//      now.debug();
        inq[now.x][now.y][now.k]=0;
        if(graph[now.x][now.y]&&now.k!=k){//加油,加满达到k 
            if(dist[now.x][now.y][k]>dist[now.x][now.y][now.k]+a){
                dist[now.x][now.y][k]=dist[now.x][now.y][now.k]+a;
                if(!inq[now.x][now.y][k]){
                    inq[now.x][now.y][k]=1;
                    q.push(node(now.x,now.y,k));
                } 
            } 
            continue;//遇到油库必须加油,不能不加油就走,所以要continue,下一次从加满油的状态开始更新
        }
        else{//设油库 
            if(dist[now.x][now.y][k]>dist[now.x][now.y][now.k]+a+c){
                dist[now.x][now.y][k]=dist[now.x][now.y][now.k]+a+c;
                if(!inq[now.x][now.y][k]){
                    inq[now.x][now.y][k]=1;
                    q.push(node(now.x,now.y,k));
                } 
            } 
        }
        for(int i=0;i<4;i++){
            node nex;
            nex.x=now.x+walkx[i];
            nex.y=now.y+walky[i];
            if(now.k<1) continue;
            int w=0;//走的代价
            if(nex.x<now.x||nex.y<now.y) w=b;
            nex.k=now.k-1;
            if(nex.x>=1&&nex.y>=1&&nex.x<=n&&nex.y<=n){
                if(dist[nex.x][nex.y][nex.k]>dist[now.x][now.y][now.k]+w){
                    dist[nex.x][nex.y][nex.k]=dist[now.x][now.y][now.k]+w;
                    if(!inq[nex.x][nex.y][nex.k]){
                        inq[nex.x][nex.y][nex.k]=1;
                        q.push(nex);
                    }
                }
            }
        }
    }
    int ans=INF;
    for(int i=0;i<=k;i++) ans=min(ans,dist[n][n][i]);
    return ans;
}
int main(){
    scanf("%d %d %d %d %d",&n,&k,&a,&b,&c);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&graph[i][j]);
        }
    }
    printf("%d",spfa());
}