• 【刷题】LOJ 6223 「网络流 24 题」汽车加油行驶问题


    题目描述

    给定一个 ( ext{N} imes ext{N}) 的方形网格,设其左上角为起点◎,坐标为 ( ext{(1,1)})( ext{X}) 轴向右为正, ( ext{Y}) 轴向下为正,每个方格边长为 1 ,如图所示。

    一辆汽车从起点◎出发驶向右下角终点▲,其坐标为 (( ext{N}, ext{N}))

    在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守如下规则:

    • 汽车只能沿网格边行驶,装满油后能行驶 ( ext{K}) 条网格边。出发时汽车已装满油,在起点与终点处不设油库。

    • 汽车经过一条网格边时,若其 ( ext{X}) 坐标或 ( ext{Y}) 坐标减小,则应付费用 ( ext{B}) ,否则免付费用。

    • 汽车在行驶过程中遇油库则应加满油并付加油费用 ( ext{A})

    • 在需要时可在网格点处增设油库,并付增设油库费用 ( ext{C}) (不含加油费用 ( ext{A}) )。

    • (N , K , A , B , C) 均为正整数, 且满足约束: (2leq ext{N} leq 100, 2 leq ext{K} leq 10)

    设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。

    输入格式

    文件的第一行是 ( ext{N,K,A,B,C}) 的值。

    第二行起是一个 ( ext{N}* ext{N})0-1 方阵,每行 (N) 个值,至 ( ext{N}+1) 行结束。

    方阵的第 ( ext{i}) 行第 ( ext{j}) 列处的值为 1 表示在网格交叉点 (( ext{i}, ext{j})) 处设置了一个油库,为 0 时表示未设油库。各行相邻两个数以空格分隔。

    输出格式

    程序运行结束时,输出最小费用。

    样例

    样例输入

    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
    

    样例输出

    12
    

    数据范围与提示

    (2leq nleq 100)

    (2 leq k leq 10)

    题解

    又不是网络流

    (f[i][j]) 代表到 (i) 号点,油量为 (j) 的最小代价

    跑类似SPFA的东西就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=10000+10,MAXK=10+5,inf=0x3f3f3f3f;
    int n,m,k,A,B,C,G[110][110],f[MAXN][MAXK],p[MAXN][MAXK],dr[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
    struct node{
    	int x,y,w;
    };
    std::queue<node> q;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline int id(int x,int y)
    {
    	return (x-1)*n+y;
    }
    inline void SPFA()
    {
    	memset(f,inf,sizeof(f));
    	q.push((node){1,1,k});
    	f[1][k]=0;
    	p[id(1,1)][k]=1;
    	while(!q.empty())
    	{
    		node pr=q.front();
    		q.pop();
    		int x=pr.x,y=pr.y,pt=id(x,y),w=pr.w;
    		p[pt][w]=0;
    		if(G[x][y]&&w!=k)
    		{
    			if(f[pt][w]+A<f[pt][k])
    			{
    				f[pt][k]=f[pt][w]+A;
    				if(!p[pt][k])p[pt][k]=1,q.push((node){x,y,k});
    			}
    			continue;
    		}
    		else if(!G[x][y])
    		{
    			if(f[pt][w]+C+A<f[pt][k])
    			{
    				f[pt][k]=f[pt][w]+C+A;
    				if(!p[pt][k])p[pt][k]=1,q.push((node){x,y,k});
    			}
    		}
    		if(w)
    		{
    			for(register int i=0;i<4;++i)
    			{
    				int dx=x+dr[i][0],dy=y+dr[i][1];
    				if(dx<1||dx>n||dy<1||dy>n)continue;
    				if(f[id(dx,dy)][w-1]>f[pt][w]+(i>1?B:0))
    				{
    					f[id(dx,dy)][w-1]=f[pt][w]+(i>1?B:0);
    					if(!p[id(dx,dy)][w-1])p[id(dx,dy)][w-1]=1,q.push((node){dx,dy,w-1});
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	read(n);read(k);read(A);read(B);read(C);
    	for(register int i=1;i<=n;++i)
    		for(register int j=1;j<=n;++j)read(G[i][j]);
    	SPFA();
    	int ans=inf;
    	for(register int i=0;i<=k;++i)chkmin(ans,f[id(n,n)][i]);
    	write(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    微博个人中心效果
    微博弹性按钮
    ios9 3dtouch 博客
    去掉导航栏阴影
    模态全屏模式,实现半透明效果
    剪切图片
    修改push动画的方向
    数据库链接池终于搞对了,直接从100ms到3ms
    如何在Java代码中去掉烦人的“!=null”
    面试官:请讲下接口具体怎么优化!
  • 原文地址:https://www.cnblogs.com/hongyj/p/9441223.html
Copyright © 2020-2023  润新知