链接:

洛谷

LOJ

题目大意:

一辆汽车从 \((1,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\)

正文:

众所周知,网络流 24 题都不是网络流。

本题就在广搜的壳子上套 dij 或 SPFA。

代码:

const int N = 110, K = 20;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != \'-\' && (c < \'0\' || c > \'9\')) c = getchar();
	if (c == \'-\') f = -f, c = getchar();
	while (c >= \'0\' && c <= \'9\') x = (x << 3) + (x << 1) + c - \'0\', c = getchar();
	return x * f;
}

int n, m, A, B, C;
int a[N][N];

struct node
{
	int dis, x, y, k;
	bool operator < (const node &a) const
	{
		return dis > a.dis;
	}
};

priority_queue<node> q;
int dis[N][N][K];
bool vis[N][N][K];

int dx[5] = {0, -1, 0, 1, 0},
    dy[5] = {0, 0, -1, 0, 1};

void dij(node s)
{
	memset (dis, 127 / 3, sizeof dis);
	memset (vis, 0, sizeof vis);
	dis[s.x][s.y][s.k] = 0;
	q.push(s);
	while (!q.empty())
	{
		node u = q.top(); q.pop();
		if (vis[u.x][u.y][u.k]) continue;
		vis[u.x][u.y][u.k] = 1;
		if (a[u.x][u.y] && u.k != m)
		{
			if (dis[u.x][u.y][u.k] + A < dis[u.x][u.y][m])
			{
				dis[u.x][u.y][m] = dis[u.x][u.y][u.k] + A;
				q.push((node){dis[u.x][u.y][m], u.x, u.y, m});
			} 
			continue;
		}
		else
		{
			if (dis[u.x][u.y][u.k] + A + C < dis[u.x][u.y][m])
			{
				dis[u.x][u.y][m] = dis[u.x][u.y][u.k] + A + C;
				q.push((node){dis[u.x][u.y][m], u.x, u.y, m});
			} 
		}
		if (u.k > 0)
			for (int i = 1; i <= 4; i ++)
			{
				if (u.x + dx[i] < 1 || u.x + dx[i] > n || u.y + dy[i] < 1 || u.y + dy[i] > n) continue;
				if (dis[u.x][u.y][u.k] + (i <= 2) * B < dis[u.x + dx[i]][u.y + dy[i]][u.k - 1])
					{
						dis[u.x + dx[i]][u.y + dy[i]][u.k - 1] = dis[u.x][u.y][u.k] + (i <= 2) * B;
						q.push((node){dis[u.x + dx[i]][u.y + dy[i]][u.k - 1], u.x + dx[i], u.y + dy[i], u.k - 1});
					} 
			}
	}
}

int ans = 1e9;

int main()
{
	n = Read(), m = Read(), A = Read(), B = Read(), C = Read();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			a[i][j] = Read();
	dij ((node){0, 1, 1, m});
	
	for (int i = 0; i <= m; i++)
		ans = min(ans, dis[n][n][i]);
		
	printf ("%d\n", ans);
	return 0;
}

版权声明:本文为GJY-JURUO原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/GJY-JURUO/p/14798055.html