ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

汽车加油行驶问题 题解

2022-06-16 00:03:32  阅读:140  来源: 互联网

标签:leq int 题解 网格 行驶 kk 油库 加油 dis


题目描述

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

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

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

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

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

  3. 汽车在行驶过程中遇油库则应加满油并付加油费用 \(A\)。

  4. 在需要时可在网格点处增设油库,并付增设油库费用 \(C\)(不含加油费用\(A\) )。

  5. \(N,K,A,B,C\) 均为正整数, 且满足约束: \(2\leq N\leq 100,2 \leq K \leq 10\)。

设计一个算法,求出汽车从起点出发到达终点所付的最小费用。

输入格式

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

第二行起是一个\(N\times N\) 的 \(0-1\) 方阵,每行 \(N\) 个值,至 \(N+1\) 行结束。

方阵的第 \(i\) 行第 \(j\) 列处的值为 \(1\) 表示在网格交叉点 \((i,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

数据范围:\(2 \leq n \leq 100,2 \leq k \leq 10\)


分层图板子题了属于是吧,思路非常简单粗暴,主要注意建图的hash问题,容易出现疏漏。

图分为 \(k+1\) 层,箭头所指可以直达,蓝线自下而上需要付费(即最短路边权,费用流费用),黄线自高层连到基层需要付费(同上),最后在每一层的右下扫一遍取最小值即可。

摘自洛谷用户:Adove

注意细节:到达加油站有两种情况

  • 非满油,花 \(A\) 加油。

  • 满油,正常向四周转移。

Code.

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10,M=N*5;
int n,k,a,b,c,idx,h[M],ne[M],e[M],w[M],dis[M];
bool st[M];
void add(int x,int y,int z,int xx,int yy,int zz,int c)
{
	int u=n*n*(z-1)+(x-1)*n+y,v=n*n*(zz-1)+(xx-1)*n+yy;
	ne[++idx]=h[u],e[idx]=v,w[idx]=c,h[u]=idx;
}
void spfa()
{
	for(int i=0;i<=(n*n*(k+1));i++) dis[i]=0x3f3f3f3f;
	queue<int> q;
	dis[1]=0;st[1]=1;q.push(1);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		st[u]=0;
		for(int i=h[u];~i;i=ne[i])
		{
			int j=e[i];
			if(dis[j]>dis[u]+w[i])
			{
				dis[j]=dis[u]+w[i];
				if(!st[j]) q.push(j),st[j]=1;
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof h);
	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++)
		{
			int x;
			scanf("%d",&x);
			for(int kk=1;kk<=k;kk++) add(i,j,kk,i,j,kk+1,0);
			if(x)
			{
				for(int kk=2;kk<=k+1;kk++) add(i,j,kk,i,j,1,a);
				
				if(i < n) add(i,j,1,i+1,j,2,0);
				if(j < n) add(i,j,1,i,j+1,2,0);
				if(i > 1) add(i,j,1,i-1,j,2,b);
				if(j > 1) add(i,j,1,i,j-1,2,b);
			}
			else
			{
				for(int kk=1;kk<=k;kk++)
				{
					if(i < n) add(i,j,kk,i+1,j,kk+1,0);
					if(j < n) add(i,j,kk,i,j+1,kk+1,0);
					if(i > 1) add(i,j,kk,i-1,j,kk+1,b);
					if(j > 1) add(i,j,kk,i,j-1,kk+1,b);
				}
				for(int kk=2;kk<=k+1;kk++) add(i,j,kk,i,j,1,a+c);
			}
		}
	spfa();
	int ans=0x3f3f3f3f;
	for(int i=1;i<=k+1;i++) ans=min(ans,dis[n*n*i]);
	printf("%d",ans);
	return 0;
}

标签:leq,int,题解,网格,行驶,kk,油库,加油,dis
来源: https://www.cnblogs.com/EastPorridge/p/16380368.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有