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

时间: 2024-10-11 13:27:31

P4009 汽车加油行驶问题的相关文章

洛谷 P4009 汽车加油行驶问题 【最小费用最大流】

分层图,建k层,设(i,j,0)为点(i,j)的满油状态,全图的流量都是1,因为重复走到一个点没有意义.如果当前点是加油站,那么它向它上左的点连费用为a的边,向下右连费用为a+b的边: 否则,这个点的所有层向零层连费用为a+c的边表示建加油站和加油,其他的当前点是加油站的情况连即可,但是不用加a.然后s向(1,1,0)连,(n,n)的所有层向t连,最后跑最小费用最大流. #include<iostream> #include<cstdio> #include<cmath>

【线性规划与网络流24题】汽车加油行驶问题 分层图

汽车加油行驶问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 给定一个 N*N的方形网格,设其左上角为起点◎,坐标为( 1,1),X轴向右为正, Y轴向下为正,每一个方格边长为 1,如图所看到的.一辆汽车从起点◎出发驶向右下角终点▲,其坐标为( N,N).在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油.汽车在行驶过程中应遵守例如以下规则: (1)汽车仅仅能沿网格边行驶,装满油后能行驶 K条网格边.出发时汽车已装满油,在起点与终

【网络流24题】汽车加油行驶问题(最短路)

[网络流24题]汽车加油行驶问题(最短路) 题面 Cogs 题解 还是SPFA呀... 把剩余的油量直接压进状态里面就好 额外加一个原地加油的决策就行 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map

汽车加油行驶问题

汽车加油行驶问题 网络流24题中的,单好像不用费用流水过更快?(我没测过) 广搜搞一下,按剩余油量分层. #include <queue> #include <cstdio> #include <cstring> const int dx[4]= {0,0,1,-1},dy[4]= {1,-1,0,0}; int n,k,a,b,c,g[105][105],dis[105][105][15],ans=0x3f3f3f3f; struct node {int x,y,re

汽车加油行驶(cogs 737)

?问题描述:给定一个N*N 的方形网格,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y轴向下为正,每个方格边长为1,如图所示.一辆汽车从起点◎出发驶向右下角终点▲,其坐标为(N,N).在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油.汽车在行驶过程中应遵守如下规则:(1)汽车只能沿网格边行驶,装满油后能行驶K 条网格边.出发时汽车已装满油,在起点与终点处不设油库.(2)汽车经过一条网格边时,若其X 坐标或Y 坐标减小,则应付费用B,否则免付费用.(3)汽车在行驶过程中遇油库则应

【网络流24题15】汽车加油行驶问题

题面戳我 题目描述 给定一个 \(N×N\) 的方形网格,设其起点坐标\((1,1)\),\(X\)轴向右为正,\(Y\)轴向下为正,每个方格边长为\(1\),终点坐标为 \((N,N)\). 在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油.汽车在行驶过程中应遵守如下规则: 汽车只能沿网格边行驶,装满油后能行驶 \(K\) 条网格边.出发时汽车已装满油,在起点与终点处不设油库. 汽车经过一条网格边时,若其\(X\)坐标或\(Y\)坐标减小,则应付费用 \(B\),否则免付费用. 汽车在

网络流24题 之十五 汽车加油行驶问题 分层图

题目大意:给出一张网格图,描述了每个点是否是加油站,然后给出以下规则. 1.油量限制,一次加油之后只能行驶k步,向下行驶和向右行驶的时候不增加花费,否则增加B的花费. 2.在没油的时候,若该点没有加油站,就建立一个加油站.花费C. 3.加油花费A. 思路:分层图.f[i][j][k]表示在(i,j)处油箱中还有k的油的时候的最小花费,然后分三种情况更新. (delta = 往回走的B花费) 1.若当前节点有加油站,就必须加油.到下一个节点是还有k - 1的油量,花费last + A + delt

【网络流24题----15】汽车加油行驶问题

喜闻乐见的分层图最短路,注意到了加油站是强制要加满油的 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 110 10 #

[CODEVS1912] 汽车加油行驶问题(分层图最短路)

传送门 吐槽:神tm网络流 dis[i][j][k] 表示到 (i, j) 还有 k 油的最优解 然后跑spfa,中间分一大堆情况讨论 1.当前队头还有油 1.目标点有加油站——直接过去 2.目标点每加油站——1.直接过去 2.在当前点召唤一个加油站再过去 2.没油——召唤加油站再走 ——代码 1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5