http://acm.uestc.edu.cn/#/problem/show/381

题目大意:给你两个棋子:车、马,再给你一个n*m的网格,从s出发到t,你可以选择车或者选择马开始走,图中有一些障碍物,该障碍物是不能走的,走的图中有换一次棋子的机会,问最少需要几次能从s走到t?

思路:bfs来4次就好了。两次记录从s->t,两次是t->s。然后暴力一下就出来了,复杂度为4*n*m*log

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = + ;
const int inf = 0x3f3f3f3f;
char ch[maxn][maxn];
int n, m;
pair<int, int> s, t;
int rook[maxn][maxn], knight[maxn][maxn];
int r1[maxn][maxn], k1[maxn][maxn];
int r2[maxn][maxn], k2[maxn][maxn];
int dx[] = {-, -, -, , , , , -};
int dy[] = {-, , , , , -, -, -}; int bfs1(int a, int b){
memset(rook, 0x3f, sizeof(rook));
queue<pair<int, int> > que;
que.push(mk(a, b));
rook[a][b] = ;
while (!que.empty()){
pair<int, int> p = que.front(); que.pop();
int x = p.fi, y = p.se;
///if (flag && x == s.fi && y == s.se) break;
int lb = , rb = ;
for (int i = x - ; i > ; i--)
if (ch[i][y] == '#') {lb = i; break;}
for (int i = x; i <= n; i++)
if (ch[i][y] == '#') {rb = i; break;}
if (rb == ) rb = n + ;
///lb和rb都是不能走的
for (int i = lb + ; i < rb; i++){
if (i != x && rook[i][y] > rook[x][y] + ){
rook[i][y] = rook[x][y] + ;
que.push(mk(i, y));
}
}
lb = , rb = ;
for (int i = y - ; i > ; i--)
if (ch[x][i] == '#') {lb = i; break;}
for (int i = y; i <= m; i++)
if (ch[x][i] == '#') {rb = i; break;}
if (rb == ) rb = m + ;
for (int i = lb + ; i < rb; i++){
if (i != y && rook[x][i] > rook[x][y] + ){
rook[x][i] = rook[x][y] + ;
que.push(mk(x, i));
}
}
}
return rook[s.fi][s.se];
} int bfs2(int a, int b){
memset(knight, 0x3f, sizeof(knight));
queue<pair<int, int> > que;
que.push(mk(a, b));
knight[a][b] = ;
while (!que.empty()){
pair<int, int> p = que.front(); que.pop();
int x = p.fi, y = p.se;
///if (flag && x == s.fi && y == s.se) break;
for (int i = ; i < ; i++){
int nx = x + dx[i], ny = y + dy[i];
if (nx <= || ny <= || nx > n || ny > m) continue;
if (ch[nx][ny] == '#') continue;
if (knight[nx][ny] > knight[x][y] + ){
knight[nx][ny] = knight[x][y] + ;
que.push(mk(nx, ny));
}
}
}
return rook[s.fi][s.se];
} int solve(){
//printf("k = %d r = %d\n", k[s.fi][s.se], r[s.fi][s.se]);
//int mini = min(r2[t.fi][t.se], k2[t.fi][t.se]);
int mini = inf;
for (int i = ; i <= n; i++){
for (int j = ; j <= m; j++){
if (ch[i][j] == '#') continue;
if (r1[i][j] < inf && k2[i][j] < inf) mini = min(mini, r1[i][j] + k2[i][j]);
if (k1[i][j] < inf && r2[i][j] < inf) mini = min(mini, k1[i][j] + r2[i][j]);
}
}
if (mini == inf) return -;
return mini;
} int main(){
int T; cin >> T;
for (int kase = ; kase <= T; kase++){
cin >> n >> m;
for (int i = ; i <= n; i++){
scanf("%s", ch[i] + );
for (int j = ; j <= m; j++){
if (ch[i][j] == 's') s = mk(i, j);
if (ch[i][j] == 't') t = mk(i, j);
}
}
memset(r1, inf, sizeof(r1)); memset(k1, inf, sizeof(k1));
memset(r2, inf, sizeof(r2)); memset(k2, inf, sizeof(k2));
bfs1(t.fi, t.se); bfs2(t.fi, t.se);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
r1[i][j] = rook[i][j], k1[i][j] = knight[i][j];
bfs1(s.fi, s.se); bfs2(s.fi, s.se);
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
r2[i][j] = rook[i][j], k2[i][j] = knight[i][j];
printf("Case #%d: %d\n", kase, solve());
}
return ;
}

bfs UESTC 381 Knight and Rook的更多相关文章

  1. 迷宫问题bfs, A Knight's Journey(dfs)

    迷宫问题(bfs) POJ - 3984   #include <iostream> #include <queue> #include <stack> #incl ...

  2. Three Pieces CodeForces - 1065D (BFS)

    链接 大意: n*n棋盘, 每个格子写有数字, 各不相同, 范围[1,n*n], 初始在数字1的位置, 可以操纵knight,bishop,rook三种棋子, 每走一步花费1, 交换棋子花费1, 问按 ...

  3. 记录----第一次使用BFS(广度搜索)学习经验总结

    学习经验记录与分享—— 最近在学习中接触到了一种解决最短路径的实用方法----BFS(广度搜索),在这里总结并分享一下第一次学习的经验. 首先第一个要了解的是"queue"(队列函 ...

  4. zju 1091

    // Traveling Knight Problem #include "stdafx.h" #include <string> #include <strin ...

  5. x01.xiangqi: 走动棋子

    采用 pygame 写的象棋程序,目前只完成绘制棋盘与走动棋子,还没考虑规则等问题. 1. 代码: """ x01.xiangqi (c) 2019 by x01&quo ...

  6. [JLOI2008]将军

    Description 刘先生最近在学习国际象棋,使用一个叫"jloi-08"的游戏软件.在这个游戏里,不但可以和电脑普通地对弈,还可以学习著名的棋局,还有针对初学者的规则指导等丰 ...

  7. c++ 广度优先搜索(宽搜)

    c++ bfs基本应用 Knight Moves 题目描述 贝茜和她的表妹在玩一个简化版的国际象棋.棋盘如图所示: 贝茜和表妹各有一颗棋子.棋子每次移一步,且棋子只能往如图所示的八个方向移动.比赛的规 ...

  8. HDU 1372 Knight Moves (bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1372 Knight Moves Time Limit: 2000/1000 MS (Java/Othe ...

  9. HDU 1372 Knight Moves【BFS】

    题意:给出8*8的棋盘,给出起点和终点,问最少走几步到达终点. 因为骑士的走法和马的走法是一样的,走日字形(四个象限的横竖的日字形) 另外字母转换成坐标的时候仔细一点(因为这个WA了两次---@_@) ...

随机推荐

  1. Arrar.prototype.map()的用法

    ---恢复内容开始--- map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组. array.map(callback[, thisArg]) 注:[]在语法中[]内的内 ...

  2. Django 1.8 - “No migrations to apply” when run migrate after makemigrations 解决办法

    解决办法 1 删除应用migrations目录 2 删除MySQL中django_migrations中对应的行(delete from django_migrations where app='ap ...

  3. Qt 5.7 > QML

    本文档翻译自Qt官方文档: http://doc.qt.io/qt-5/qtqml-index.html Qt QML Qt QML模块使用QML语言为开发应用与库提供一个框架.它定义并实现了语言与引 ...

  4. javascript 中的call和apply

    一.作用及应用场景 call和apply是Function的方法,他的第一个参数是this,第二个是Function的参数.call 和 apply 都是为了改变某个函数运行时的 context 即上 ...

  5. JavaBean 反射机制实现自动配置数据

    声明:该版本是没完成的.该博文只做记录代码用 String memberType(String name) throws Exception { return getType(getClass().g ...

  6. Linux后门账户控制

    赋予用户sudo权限 vi /etc/sudoers 添加如下一行: USER ALL=(ALL) NOPASSWD: ALL (实现当前用户允许转换成任意用户及执行任意命令) 添加root权限账户 ...

  7. 第六十八节,htnl全局属性和其他属性

    htnl全局属性和其他属性 学习要点: 1.实体 2.元数据 3.全局属性 本章主要探讨HTML5中的HTML实体.以及HTML核心构成的元数据,最后了解一下HTML中的全局属性. 一.实体 HTML ...

  8. em,strong,b,i的区别

    文章来源: http://www.zhihu.com/question/19551271 默认样式: strong=b=粗体 em=i=斜体   HTML4.01: strong,em代表语义,从语义 ...

  9. Linux随笔(安装ftp,安装jdk,安装 tomcat,安装redis,安装MySQL)

    su: authentication failure 解决办法:sudo passwd root  更改密码即可 确认虚拟机用到的联网方式是桥接模式,不然Windows是ping不通Linux的,确保 ...

  10. 浙大pat 1035题解

    1035. Password (20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue To prepare f ...