【ybt高效进阶3-3-4】【luogu P4009】汽车加油 / 汽车加油行驶问题
高效 进阶 汽车 Luogu ybt 问题 加油
2023-09-27 14:28:29 时间
汽车加油 / 汽车加油行驶问题
题目链接:ybt高效进阶3-3-4 / luogu P4009
题目大意
你要从一个网格的左上角点走到右下角点。
可以想四个方向行动,然后自己可以独立走 K 步,走到油站就重新算,但是有花费 A。可以自己建油站,费用为 C。
如果你要走向 x 或 y 坐标减少的地方,还要花费 B。
问你最小花费。
思路
看到数据范围,发现很小,我们考虑把点拆开。
我们让原来的一个点拆开,原来只是记录在哪个位置,现在我们把拆开的点还多一个值,就是还能走多少步数(在不去油站的情况下)
那我们考虑怎么转移。
那首先,我们可以在这个地方弄油站(要么就现成,要么就自己弄)。第二,我们可以网四个方向走,而且如果是往上或往左,要记得费用加
B
B
B。
然后啊,还有一点就是,如果这个地方原来就是有油站的,那你就会被强迫消费,那你剩余行走次数就只能从
K
K
K 开始转移。
然后你会发现它可以直接用最短路来做,我这里用的是 SPFA。
你就把每个状态都弄一个编号,然后转移所加上的值就是连边的边的权值。边连着的点就是从哪个状态转移到哪个状态。
听说还可以用网络流来搞。
以后再说吧。
代码
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
struct node {
int x, to, nxt;
}e[2000001];
int n, K, le[1000001], KK;
long long a, b, c, dis[1000001], ans;
int pl[101][101];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int b_c[4] = {0, 0, 1, 1};
bool in[1000001];
queue <int> q;
int get_num(int x, int y, int oil) {
return oil * (n * n) + (x - 1) * n + y - 1 + 1;
}
void add(int x, int y, int z) {
e[++KK] = (node){z, y, le[x]}; le[x] = KK;
}
bool check(int x, int y) {
if (x < 1 || x > n) return 0;
if (y < 1 || y > n) return 0;
return 1;
}
void spfa() {//SPFA跑最短路
memset(dis, 0x7f, sizeof(dis));
in[get_num(1, 1, K)] = 1;
dis[get_num(1, 1, K)] = 0;
q.push(get_num(1, 1, K));
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = le[now]; i; i = e[i].nxt)
if (dis[e[i].to] > dis[now] + e[i].x) {
dis[e[i].to] = dis[now] + e[i].x;
if (!in[e[i].to]) {
in[e[i].to] = 1;
q.push(e[i].to);
}
}
in[now] = 0;
}
}
int main() {
scanf("%d %d %lld %lld %lld", &n, &K, &a, &b, &c);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &pl[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
for (int k = 0; k < K; k++)//加油
if (pl[i][j]) add(get_num(i, j, k), get_num(i, j, K), a);
else add(get_num(i, j, k), get_num(i, j, K), a + c);
for (int k = 0; k < 4; k++)//走
if (check(i + dx[k], j + dy[k])) {
if (!pl[i][j]) {
for (int l = 1; l <= K; l++) {
if (b_c[k]) add(get_num(i, j, l), get_num(i + dx[k], j + dy[k], l - 1), b);
else add(get_num(i, j, l), get_num(i + dx[k], j + dy[k], l - 1), 0);
}
}
else {//强制消费
if (b_c[k]) add(get_num(i, j, K), get_num(i + dx[k], j + dy[k], K - 1), b);
else add(get_num(i, j, K), get_num(i + dx[k], j + dy[k], K - 1), 0);
}
}
}
spfa();
ans = dis[0];
for (int i = 0; i <= K; i++)
ans = min(ans, dis[get_num(n, n, i)]);//统计,到终点的时候剩下步数没有规定,都可以,要枚举找最小值
printf("%lld", ans);
return 0;
}
相关文章
- 建议测试人员提单格式,统一、高效一步到位!
- 2021Android目前最稳定和高效的UI适配方案!深度好文
- SpringBoot2 整合 Drools规则引擎,实现高效的业务规则
- 高效、精准、全面 山石网科数据安全产品线面市
- 升级光伏供应链体系,供应商系统规范供应商管理,促进企业与供应商高效协同
- 破局企业数字化采购难题,采购系统标准化采购结算流程,实现高效协同
- 《中国人工智能学会通讯》——11.75 复杂数据融合与高效学习
- 高效vim插件
- Abyss Web服务器,高效防墙系统
- 怎么才能最短时、高效、踏实的学习 Python?
- [.NET] 《Effective C#》快速笔记 - C# 高效编程要点补充
- 【ybt金牌导航1-1-1】【ybt高效进阶6-6-3】路径长度
- 【ybt高效进阶1-2-3】【luogu P2859】畜栏预定 / Stall Reservations S
- 【ybt高效进阶6-4-3】【luogu P2480】古代猪文(数学)(EXCRT / CRT)(Lucas定理)(欧拉定理)
- 【ybt高效进阶6-3-4】中国剩余定理(数学)
- 【ybt高效进阶6-6-1】【luogu P1297】单选错位(期望)
- 【ybt高效进阶6-5-2】数字游戏(博弈论)
- 【ybtoj高效进阶 21171】简单序列(DP)
- 【ybtoj高效进阶 21278】内需消费(线段树)(广义矩阵乘法)(DP)
- 【ybtoj高效进阶 21266】历经磨难(单调队列优化DP)
- 【ybt高效进阶4-2-3】【luogu UVA12983】严格上升子序列数 / The Battle of Chibi
- 【ybt高效进阶1-1-3】【luogu P1025】数的划分
- 【SSL 2510】【luogu P2886】【ybt高效进阶6-1-5】奶牛接力 / Cow Relays G(矩阵乘法变形)
- 【ybtoj高效进阶 21288】头文件 B(线段树)(图论)
- 【ybt高效进阶2-3-3】周期长度和
- 【ybtoj高效进阶 21272】生命游戏(bfs)(二分)
- 【ybt高效进阶1-5-2】【luogu P3456】山峰和山谷 / GRZ-Ridges and Valleys
- 【ybt高效进阶2-3-4】子串拆分
- 【ybt高效进阶2-1-3】单词替换
- 【高效开发工具系列】uTools介绍与使用