链接:
题目大意:
一辆汽车从 ((1,1)) 到 ((N,N))。
在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守如下规则:
-
汽车只能沿网格边行驶,装满油后能行驶 (K) 条网格边。出发时汽车已装满油,在起点与终点处不设油库。
-
汽车经过一条网格边时,若其 (X) 坐标或 (Y) 坐标减小,则应付费用 (B) ,否则免付费用。
-
汽车在行驶过程中遇油库则应加满油并付加油费用 (A)。
-
在需要时可在网格点处增设油库,并付增设油库费用 (C)(不含加油费用(A) )。
-
(N,K,A,B,C) 均为正整数, 且满足约束: (2leq Nleq 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
", ans);
return 0;
}