题目链接

首先拆点,把每个点拆成4个点,表示到达这个点的时候赛车的朝向。

然后考虑连边。

相邻同向并且都是可以走的点直接连边权1的边。

至于怎么转向,只需在每个点\(i\)向每个方向一直拓展直到不能走为止,如果当前点的深度大于灵敏度,从\(i\)向这个点的其它3个方向都连一条边权为这个点的深度的边。

然后跑\(SPFA\)(至于为什么是\(SPFA\),我才不会告诉你是博主懒),这样你可以获得\(90pts\)。

为什么?因为我们最多要跑\(10\)次,而每次连边的时间复杂度都是\(O(n^3)\)级别的,加上要跑\(SPFA\),很容易超时。

所以考虑一个优化,显然每次连边有很多重复的地方,因为灵敏度为\(2\)的情况肯定也把灵敏度为\(3\)的情况的所有边都连了。

所以我们不妨反过来跑,灵敏度从\(10\)到\(1\),每次只连长度刚好为灵敏度的转向边,用栈记录一下答案就行了。

\(90pts\):

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#define Open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define Close fclose(stdin); fclose(stdout);
#define O(x) cout << #x << "=" << x << endl;
using namespace std;
const int MAXN = 10010 << 2;
const int MAXM = 5000000;
struct Edge{
int next, to, dis;
}e[MAXM << 1];
int head[MAXN], num, dis[MAXN], vis[MAXN], a[110][110];
inline void Add(int u, int v, int dis){
e[++num] = (Edge){ head[u], v, dis }; head[u] = num;
}
int n, m, N, l[] = { -1, 1, 0, 0 }, r[] = { 0, 0, -1, 1 }, sx, sy, px, py;
inline int id(int x, int y, int direct){
return direct * N + (x - 1) * m + y;
}
queue <int> q;
int work(int check){
num = 0; memset(head, 0, sizeof head);
memset(dis, 127, sizeof dis);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(!a[i][j]) continue;
for(int k = 0; k < 4; ++k){
int x = i + l[k], y = j + r[k];
if(!a[x][y]) continue;
Add(id(i, j, k), id(x, y, k), 1);
for(int o = 1; a[x][y]; x += l[k], y += r[k], ++o)
if(o >= check)
for(int l = 0; l < 4; ++l)
if(l != k)
Add(id(i, j, k), id(x, y, l), o);
}
}
dis[id(sx, sy, 0)] = dis[id(sx, sy, 1)] = dis[id(sx, sy, 2)] = dis[id(sx, sy, 3)] = 0;
vis[id(sx, sy, 0)] = vis[id(sx, sy, 1)] = vis[id(sx, sy, 2)] = vis[id(sx, sy, 3)] = 1;
q.push(id(sx, sy, 0)); q.push(id(sx, sy, 1)); q.push(id(sx, sy, 2)); q.push(id(sx, sy, 3));
while(q.size()){
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = head[u]; i; i = e[i].next)
if(dis[e[i].to] > dis[u] + e[i].dis){
dis[e[i].to] = dis[u] + e[i].dis;
if(!vis[e[i].to]){
vis[e[i].to] = 1;
q.push(e[i].to);
}
}
}
int ans = min(min(dis[id(px, py, 0)], dis[id(px, py, 1)]), min(dis[id(px, py, 2)], dis[id(px, py, 3)]));
if(ans < 10000000) return printf("%d %d\n", check, ans), 0;
else return 1;
}
int main(){
scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &px, &py); N = n * m;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf("%d", &a[i][j]);
for(int i = 1; i <= 10; ++i)
if(work(i))
break;
return 0;
}

\(100pts\)

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#define Open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define Close fclose(stdin); fclose(stdout);
#define O(x) cout << #x << "=" << x << endl;
using namespace std;
const int MAXN = 10010 << 2;
const int MAXM = 5000000;
struct Edge{
int next, to, dis;
}e[MAXM << 1];
int head[MAXN], num, dis[MAXN], vis[MAXN], a[110][110], s[12], top;
inline void Add(int u, int v, int dis){
e[++num] = (Edge){ head[u], v, dis }; head[u] = num;
}
int n, m, N, l[] = { -1, 1, 0, 0 }, r[] = { 0, 0, -1, 1 }, sx, sy, px, py;
inline int id(int x, int y, int direct){
return direct * N + (x - 1) * m + y;
}
queue <int> q;
void work(int check){
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(!a[i][j]) continue;
for(int k = 0; k < 4; ++k){
for(int p = 1, x = i + l[k], y = j + r[k]; a[x][y]; ++p, x += l[k], y += r[k])
if(p == check){
for(int l = 0; l < 4; ++l)
if(l != k)
Add(id(i, j, k), id(x, y, l), check);
break;
}
}
}
memset(dis, 127, sizeof dis);
dis[id(sx, sy, 0)] = dis[id(sx, sy, 1)] = dis[id(sx, sy, 2)] = dis[id(sx, sy, 3)] = 0;
vis[id(sx, sy, 0)] = vis[id(sx, sy, 1)] = vis[id(sx, sy, 2)] = vis[id(sx, sy, 3)] = 1;
q.push(id(sx, sy, 0)); q.push(id(sx, sy, 1)); q.push(id(sx, sy, 2)); q.push(id(sx, sy, 3));
while(q.size()){
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = head[u]; i; i = e[i].next)
if(dis[e[i].to] > dis[u] + e[i].dis){
dis[e[i].to] = dis[u] + e[i].dis;
if(!vis[e[i].to]){
vis[e[i].to] = 1;
q.push(e[i].to);
}
}
}
int ans = min(min(dis[id(px, py, 0)], dis[id(px, py, 1)]), min(dis[id(px, py, 2)], dis[id(px, py, 3)]));
if(ans < 10000000) s[++top] = ans;
}
int main(){
scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &px, &py); N = n * m;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf("%d", &a[i][j]);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(!a[i][j]) continue;
for(int k = 0; k < 4; ++k){
int x = i + l[k], y = j + r[k];
if(!a[x][y]) continue;
Add(id(i, j, k), id(x, y, k), 1);
}
}
for(int i = 10; i; --i)
work(i);
for(int Top = top, i = 1; i <= Top; ++i)
printf("%d %d\n", i, s[top--]);
return 0;
}

【洛谷 P2226】 [HNOI2001]遥控赛车比赛(最短路)的更多相关文章

  1. 题解-[HNOI2001]遥控赛车比赛

    题解-[HNOI2001]遥控赛车比赛 前置知识:记忆化搜索.\(\texttt{Bfs}\). 参考资料 https://www.luogu.com.cn/blog/CYJian/solution- ...

  2. 洛谷P2460 [SDOI2007]科比的比赛(题解)(贪心+搜索)

    科比的比赛(题解)(贪心+搜索) 标签:算法--贪心 阅读体验:https://zybuluo.com/Junlier/note/1301158 贪心+搜索 洛谷题目:P2460 [SDOI2007] ...

  3. 洛谷P2777 [AHOI2016初中组]自行车比赛

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. 洛谷P2224 [HNOI2001] 产品加工 [DP补完计划,背包]

    题目传送门 产品加工 题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时 ...

  5. 洛谷 P5304 [GXOI/GZOI2019]旅行者(最短路)

    洛谷:传送门 bzoj:传送门 参考资料: [1]:https://xht37.blog.luogu.org/p5304-gxoigzoi2019-lv-xing-zhe [2]:http://www ...

  6. 【BZOJ2763/洛谷p4563】【分层图最短路】飞行路线

    2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4630  Solved: 1797[Submit][Stat ...

  7. 洛谷P1462-通往奥格瑞玛的道路-二分+最短路

    洛谷P1462-通往奥格瑞玛的道路 题目描述 在艾泽拉斯,有\(n\)个城市.编号为\(1,2,3,...,n\). 城市之间有\(m\)条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联 ...

  8. 洛谷 P2224 [HNOI2001]产品加工 解题报告

    P2224 [HNOI2001]产品加工 题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需 ...

  9. 洛谷U14667 肝活动【比赛】 【状压dp】

    题目描述 Yume 最近在玩一个名为<LoveLive! School idol festival>的音乐游戏.他之所以喜欢上这个游戏,是因为这个游戏对非洲人十分友好,即便你脸黑到抽不出好 ...

随机推荐

  1. MongoDB 表(集合) 创建删除、数据增删改查

    MongoDB 表(集合) 创建删除和增删改查数据 创建一个集合(emp) 在创建集合之前先使用use xxx,选择数据库,如果没有会创建(并不是真正的创建,只有在数据库里面保存集合数据之后才能够真正 ...

  2. Java 8 创建 Stream 的 10 种方式,我保证你受益无穷!

    之前栈长分享过 Java 8 一系列新特性的文章,其中重点介绍了 Stream. 获取上面这份 Java 8~12 系列新特性干货文章,请在微信搜索关注微信公众号:Java技术栈,在公众号后台回复:j ...

  3. Django入门——《Python编程从入门到实践》

    Django是一个Web框架--一套用于帮助开发交互式网站的工具.Django能够响应网页请求,还能让你更轻松地读写数据库.管理用户等. 1.建立项目 开始编写一个名为"学习笔记" ...

  4. 第07组 Alpha冲刺(6/6)

    队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:博客生成的逻辑 展示GitHub当日代码/文档签入记录:(组内共用,已询问过助教小姐姐 ...

  5. 包含MANIFEST.MF的jar可执行应用指定classpath及spring boot应用增量升级打包实现

    对于不包含MANIFEST.MF,或jar包中的MANIFEST.MF未指定MainClass的jar,可以通过java命令行选项-classpath指定classpath.但是如果是包含MainCl ...

  6. [转]centos sqlite3安装及简单命令

    安装: 方法一: wget http://www.sqlite.org/sqlite-autoconf-3070500.tar.gz tar xvzf sqlite-autoconf-3070500. ...

  7. (4)Flask项目模板渲染初体验

    一.准备静态资源 将项目使用到的静态资源拷贝到static目录 二.创建前台首页html 创建templates/home/home.html页面,内容包含导航和底部版权两部分,中间内容区域为模板标签 ...

  8. Python高级笔记(十一)装饰器【面试】

    1. 需求 开发封闭原则:虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被拓展,即: 封闭:已实现的功能代码块 开发:对拓展开发 2. ...

  9. LIST<>泛型集合取得对象的属性值

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  10. [LeetCode] 71. Simplify Path 简化路径

    Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...