题目链接

首先拆点,把每个点拆成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;
}

最新文章

  1. snmp学习笔记
  2. C++ 11 中的右值引用
  3. String类常用方法小节
  4. 触动——beyond歌词
  5. Java 并发编程 Executor
  6. DML数据操作语言练习
  7. DELETE---删除记录
  8. 跨平台运行ASP.NET Core 1.0(转载)
  9. vim学习、各类插件配置与安装
  10. MySql主从搭建详细步骤
  11. 静默安装Oracle12.2数据库
  12. django之模型层(model)--多表相关操作(图书管理小练习)
  13. 机器学习进阶-目标追踪-SSD多进程执行 1.cv2.dnn.readnetFromCaffe(用于读取已经训练好的caffe模型) 2.delib.correlation_tracker(生成追踪器) 5.cv2.writer(将图片写入视频中) 6.cv2.dnn.blobFromImage(图片归一化) 10.multiprocessing.process(生成进程)
  14. ThreadPoolExecutor策略配置以及应用场景
  15. Redis面试题及答案整理
  16. 集成RabbitMQ做秒杀
  17. 理解SQL SERVER中的逻辑读,预读和物理读
  18. 【干货】PHP常见危险函数
  19. 不要忘记最后那个 default 分支
  20. luoguP4115 QTREE4 链分治

热门文章

  1. Oracle 优化SQL
  2. java捕获一个网站页面的全部图片
  3. 文件数据库sqlite3 C++ 线程安全和并发
  4. rabbitmq - 消息接收,解析xml格式数据时异常:ERROR not well-formed (invalid token): line 4, column 46
  5. openresty开发系列38--通过Lua+Redis 实现动态封禁IP
  6. Windows EXE 依赖DLL查看
  7. Mac删除自带的abc输入法
  8. python调用kafka服务(使用kafka-python库)
  9. LeetCode,3. 无重复字符的最长子串
  10. Python 推导式详解