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


    Description

    给定一个N * N 的方形网格,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y轴向下为正,每个方格边长为1,如图所示。一辆汽车从起点◎出发驶向右下角终点▲,其坐标为(N,N)。在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在 行驶过程中应遵守如下规则: 
    (1)汽车只能沿网格边行驶,装满油后能行驶K 条网格边。出发时汽车已装满油,在起点与终点处不设油库。 
    (2)汽车经过一条网格边时,若其X 坐标或Y 坐标减小,则应付费用B,否则免付费用。 
    (3)汽车在行驶过程中遇油库则应加满油并付加油费用A。 
    (4)在需要时可在网格点处增设油库,并付增设油库费用C(不含加油费用A)。 
    (5)(1)~(4)中的各数N、K、A、B、C均为正整数,且满足约束:2 £ N £ 100,2 £ K £ 10。 
    设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。

    P

    Input

    第一行是N,K,A,B,C的值。 
    第二行起是一个N * N 的0-1 方阵,每行N 个值,至N+1 行结束。方阵的第i 行第j 列处的值为1 表示在网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。各行相邻两个数以空格分隔。

    Output

    最小费用

    Sample Input

    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

    Sample Output

    12

    思路:最短路。将点(i,j)分为(i,j,0)(i,j,1)(i,j,2)...(i,j,K)分别连边。代表此时在点(i,j)还能走K条网格边。

    设要从(a,b)向(c,d)连边(两点有公共边),则:

    若(c,d)是油库,则(a,b,s)向(c,d,K)连权值为a+B的边(s=0..K)

    否则(a,b,s)向(c,d,s-1)连权值为B的边(s=1..K)

    注意没有的情况,对每个(i,j),(i,j,0)向(i,j,K)连权值为a+C的边

    解释:B:若边是反方向,B==b,否则B==0

    C:若(i,j)是油库,C==0,否则C==c

    ps.裸的最短路我以为是网络流。。。

     1 // It is made by XZZ
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 #define rep(a,b,c) for(rg int a=b;a<=c;a++)
     7 #define drep(a,b,c) for(rg int a=b;a>=c;a--)
     8 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
     9 #define il inline
    10 #define rg register
    11 #define vd void
    12 #define t (dis[i])
    13 typedef long long ll;
    14 il int gi(){
    15     rg int x=0;rg char ch=getchar();
    16     while(ch<'0'||ch>'9')ch=getchar();
    17     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    18     return x;
    19 }
    20 int num[111][111][12];
    21 char yes[111][111];
    22 const int maxn=111*111*12,maxm=maxn<<2;
    23 const int X[]={23333,0,0,1,-1},Y[]={23333,1,-1,0,0},C[]={23333,0,1,0,1};
    24 int fir[maxn],nxt[maxm],dis[maxm],w[maxm],id=1;
    25 il vd add(int a,int b,int c){
    26     nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;
    27 }
    28 il int spfa(int n,int K){
    29     int que[maxn],hd=0,tl=1,Dis[maxn];bool inque[maxn]={0};
    30     que[hd]=num[1][1][K],inque[num[1][1][K]]=1;
    31     memset(Dis,127/3,sizeof Dis),Dis[num[1][1][K]]=0;
    32     while(hd-tl){
    33         int now=que[hd];hd=(hd+1)%maxn,inque[now]=0;
    34         erep(i,now)
    35             if(Dis[now]+w[i]<Dis[t])
    36                 Dis[t]=Dis[now]+w[i],(inque[t]?666666:que[tl]=t,inque[t]=1,tl=(tl+1)%maxn);
    37     }
    38     int ret=2123333333;
    39     rep(i,0,K)ret=min(ret,Dis[num[n][n][i]]);
    40     return ret;
    41 }
    42 int main(){
    43     int n=gi(),K=gi(),a=gi(),b=gi(),c=gi(),Id=0;
    44     rep(i,1,n)rep(j,1,n)while(yes[i][j]!='0'&&yes[i][j]!='1')yes[i][j]=getchar();
    45     rep(i,1,n)rep(j,1,n)rep(k,0,K)num[i][j][k]=++Id;
    46     rep(i,1,n)rep(j,1,n)
    47         if(yes[i][j]=='0')add(num[i][j][0],num[i][j][K],a+c);
    48         else add(num[i][j][0],num[i][j][K],a);
    49     rep(i,1,n)rep(j,1,n)rep(k,1,K)
    50         rep(s,1,4)if(i+X[s]&&i+X[s]<=n&&j+Y[s]&&j+Y[s]<=n)
    51             if(yes[i+X[s]][j+Y[s]]=='0')
    52                 add(num[i][j][k],num[i+X[s]][j+Y[s]][k-1],C[s]*b);
    53             else
    54                 add(num[i][j][k],num[i+X[s]][j+Y[s]][K],a+C[s]*b);
    55     printf("%d
    ",spfa(n,K));
    56     return 0;
    57 }
    View Code
     
  • 相关阅读:
    《30天自制操作系统》06_day_学习笔记
    《30天自制操作系统》05_day_学习笔记
    《30天自制操作系统》04_day_学习笔记
    ugui Event.current.mousePosition获取的坐标原点在左上角
    场景中GameObject无法用代码隐藏问题(setActive为false)
    让camera实现类似cs第一人称视角旋转和位移
    itunesconnect如何提交被决绝过了的相同版本号
    mac下安装libpng环境
    golang实现模拟键盘按键
    cocos2d3.x在android下屏蔽多点触控
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7192191.html
Copyright © 2020-2023  润新知