【YBTOJ】【LOJ 6223】【Luogu P4009】[网络流24题]汽车加油行驶问题
链接:
题目大意:
一辆汽车从 \((1,1)\) 到 \((N,N)\)。
在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守如下规则:
-
汽车只能沿网格边行驶,装满油后能行驶 \(K\) 条网格边。出发时汽车已装满油,在起点与终点处不设油库。
-
汽车经过一条网格边时,若其 \(X\) 坐标或 \(Y\) 坐标减小,则应付费用 \(B\) ,否则免付费用。
-
汽车在行驶过程中遇油库则应加满油并付加油费用 \(A\)。
-
在需要时可在网格点处增设油库,并付增设油库费用 \(C\)(不含加油费用\(A\) )。
-
\(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;
}