P4009 汽车加油行驶问题

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

题面:https://www.luogu.org/problem/P4009

分层图,建k+1层分别表示满油到没油,然后根据当前点是否有加油站在层间建边即可.
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=200050,M=500050,INF=0x3f3f3f3f;
int n,k,a,b,c,head[N],dis[N],ans=INF,maxn,cnt,nn,inq[N];
struct node{
    int next,to,dis;
}G[M*2];
void addedge(int u,int v,int w){
    G[++cnt]=(node){head[u],v,w};
    head[u]=cnt;
}
void add(int c1,int x1,int y1,int c2,int x2,int y2,int w){
    addedge(c1*nn+(x1-1)*n+y1,c2*nn+(x2-1)*n+y2,w);
}
void spfa(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        dis[i]=INF;
    }
    q.push(0);
    inq[0]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=head[u];i;i=G[i].next){
            int v=G[i].to,w=G[i].dis;
            if(dis[u]+w<dis[v]){
                dis[v]=dis[u]+w;
                if(!inq[v]){
                    inq[v]=1;
                    q.push(v);  
                } 
            }
        }
    }
}
int main(){
    scanf("%d%d%d%d%d",&n,&k,&a,&b,&c);
    nn=n*n;
    int x;
    for(int i=1;i<=n;i++){
       for(int j=1;j<=n;j++){
            scanf("%d",&x);
            if(x==0){
                for(int p=0;p<=k-1;p++){
                    add(p,i,j,k,i,j,a+c);
                }
                for(int p=1;p<=k;p++){
                    if(i-1>0){
                        add(p,i,j,p-1,i-1,j,b);
                    }
                    if(j-1>0){
                        add(p,i,j,p-1,i,j-1,b);
                    }
                    if(i+1<=n){
                        add(p,i,j,p-1,i+1,j,0);
                    }
                    if(j+1<=n){
                        add(p,i,j,p-1,i,j+1,0);
                    }
                }
            }
            else {
                for(int p=0;p<=k-1;p++){
                    add(p,i,j,k,i,j,a);
                }
                if(i-1>0){
                    add(k,i,j,k-1,i-1,j,b);
                }
                if(j-1>0){
                    add(k,i,j,k-1,i,j-1,b);
                }
                if(i+1<=n){
                    add(k,i,j,k-1,i+1,j,0);
                }
                if(j+1<=n){
                    add(k,i,j,k-1,i,j+1,0);
                }
            }
        }
    } 
    addedge(0,k*nn+1,0);
    n=nn*(k+1);
    spfa();
    for(int p=1;p<=k+1;p++){
        ans=min(ans,dis[p*nn]);
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ukcxrtjr/p/11707507.html