【传送门】http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4020

【题目大意】从起点(sx, sy)出发,要到达(ex , ey)。每次从点(x,y)走的时候要看红绿灯,灯的状态为1时只能左右走,走到(x , y+1)或者 (x , y-1);灯为0的时候只能上下走,走到(x +1, y)或者 (x-1 , y)。现在问能不能从源点走到终点,如果能,输出最少需要走多少步。

注意(x,y)代表第x行第y列,不是传统意义上的坐标系。

【题解】求最短路一般用BFS,但是与一般的图不同,这里灯的状态是不断变化的,所以允许走的方向也不同。不妨记一个步数t, t % 2 == 1或者0时方向不同,需要入队的点也不同。

另外有这样一个事实,只要访问过的点,或者说之前已经入过队的点以后都不会再入队,证明如下:

若过之前经过一个点(x0, y0), 经过若干步骤以后,又回到了(x0, y0),那么经过了多少步呢?把沿途所有点相连,必然构成一个长方形或者一条来回的直线,很显然,他们的周长必然是2的倍数,也就是偶数,因此再到这一点时这个灯的状态和上一次经过时是一样的,所以没有任何意义。当然也可能发生了这样一个情况:主人公会在这个矩形中循环走动或者在这条线段来回走动,均无法到达终点。

【代码】

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
using namespace std; struct Node
{
//点的坐标 走过的步数
int x, y, step;
}; int dic1[] = { ,-,, };
int dic2[] = { ,,-, }; vector<vector<int> >maps;
vector<vector<bool> >vis; int sx, sy, ex, ey;
int state;
int n, m; //判断点是否能够入队
bool judge(int x, int y)
{
if (x > && x <= n && y> && y <= m && vis[x][y] == )
{
return true;
}
return false;
} //BFS求最短路
int bfs(Node s)
{
queue <Node> Q;
Q.push(s);
Node p, q;
vis[s.x][s.y] = true; while (!Q.empty())
{
p = Q.front();
Q.pop();
//如果已经到达终点就直接返回步数即可
if (p.x == ex && p.y == ey)
{
return p.step;
}
state = maps[p.x][p.y];
//看看走到这一点共走了多少步,奇数步需要反转灯的状态,偶数步相当于不用反转
if ((p.step) % == )
{
if (state == )
{
state = ;
}
else
{
state = ;
}
}
//看这一点的状态(0,1) 确定能走到那两个点,将能到达的点入队
if (state == )
{
for (int i = ; i<; i++)
{
q.x = p.x + dic1[i];
q.y = p.y + dic2[i]; if (judge(q.x, q.y) == true)
{
vis[q.x][q.y] = true;
q.step = p.step+;
Q.push(q);
}
}
}
else if (state == )
{
for (int i = ; i<; i++)
{
q.x = p.x + dic1[i];
q.y = p.y + dic2[i]; if (judge(q.x, q.y) == true)
{
vis[q.x][q.y] = true;
q.step = p.step + ;
Q.push(q);
}
}
}
}
return -;
}
int main()
{
ios::sync_with_stdio(false);
int cas;
cin >> cas;
while (cas--)
{
cin >> n >> m;
maps.clear();
vis.clear();
maps.resize(n + );
vis.resize(n + );
for (int i = ; i <= n; i++)
{
maps[i].resize(m + );
vis[i].resize(m + );
}
for (int i = ; i <= n; i++)
{
for (int j = ; j <= m; j++)
{
cin >> maps[i][j];
}
}
cin >> sx >> sy >> ex >> ey;
if (sx == ex && sy == ey)
{
cout << << endl;
continue;
}
Node t;
t.x = sx;
t.y = sy;
t.step = ;
state = maps[sx][sy]; int ans = bfs(t);
cout << ans << endl;
}
return ;
}

ZOJ - 4020 Traffic Light (BFS)的更多相关文章

  1. ZOJ - 4020 Traffic Light 【BFS】

    题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4020 题意 给出一张地图 以及起点和终点 求是否能从起点走到终点 ...

  2. [ZOJ 4020] Traffic Light

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4020 很简单的一个bfs题,是我想多了. 顺便学习一下C++的S ...

  3. zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light(广搜)

    题目链接:The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light 题解: 题意 ...

  4. zoj4020 Traffic Light(bfs+状态压缩)

    题意:每个点有两种状态,0/1,0表示只能上下方向走,1表示只能左右方向走.每走一步整个图的状态改变一次(即0->1,1->0). 数据范围:n,m<=1e15 开始迷之因为数组太大 ...

  5. ZOJ - 3890 Wumpus(BFS基础题)

    Wumpus Time Limit: 2 Seconds      Memory Limit: 65536 KB One day Leon finds a very classic game call ...

  6. ZOJ 1005 Jugs(BFS)

    Jugs In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with th ...

  7. ZOJ 1107FatMouse and Cheese(BFS)

    题目链接 分析: 一个n * n的图,每个点是一个奶酪的体积,从0,0开始每次最多可以走k步,下一步体积必须大于上一步,求最大体积和 #include <iostream> #includ ...

  8. ZOJ 3652 Maze 模拟,bfs,读题 难度:2

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4842 要注意题目中两点: 1.在踏入妖怪控制的区域那一刹那,先减行动力,然后才 ...

  9. ZOJ 3596Digit Number(BFS+DP)

    一道比较不错的BFS+DP题目 题意很简单,就是问一个刚好包含m(m<=10)个不同数字的n的最小倍数. 很明显如果直接枚举每一位是什么这样的话显然复杂度是没有上限的,所以需要找到一个状态表示方 ...

随机推荐

  1. struts1标签库

    Struts提供了五个标签库,即:HTML.Bean.Logic.Template和Nested. HTML标签 : 用来创建能够和Struts 框架和其他相应的HTML 标签交互的HTML 输入表单 ...

  2. 使用jQuery 发送Ajax

    jQuery AJAX 方法 AJAX 是一种与服务器交换数据的技术,可以在不重新载入整个页面的情况下更新网页的一部分. 下面的表格列出了所有的 jQuery AJAX 方法: 构建页面:jqlogi ...

  3. Ckeditor for Drupal

      Ckeditor for Drupal   关于Drupal的所见即所得编辑器,Ckeditor是一个不错的选择,而且可以在Ckeditor官网直接下载到专为Drupal制作的版本: http:/ ...

  4. shell脚本,tee小工具的用法。

    解释: tee是个工具 , 它的作用就是把标准输出,复制一份,扔文件里 ,原标准输出还输出,-a就相当于 >> 追加到文件里的意思.  不加就是 > 重定向到文件里去.

  5. docker资源汇总

    https://github.com/hangyan/docker-resources/blob/master/README_zh.md   https://github.com/lightning- ...

  6. PHP+Mysql实现分页

    我们在项目开发的过程中避免不了使用分页功能,拿php来说,现在市面上有很多大大小小的php框架,当然了分页这种小功能这些框架中都是拿来直接可以用的. 这些框架的分页功能使用都很方便,配置一下分页所需参 ...

  7. 四:SQL语句介绍

    前言:介绍SQL语句及其大致的分类 一:SQL语句介绍(Structured SQL Lanage) 结构化的查询语言 是一种特殊的编程语言 是一种数据库查询和程序设计语言 用于存取数据及查询.更新和 ...

  8. 利用js实现图片展开与收缩

    1.元素居中放大: 1>除了要改变元素的宽高以外,还要改变元素的定位(left,top),如果图片放大一倍,那么位移放大宽高的一半. 2>元素必须是定位的.所以,在css中设置为浮动布局, ...

  9. DocView mode 0 -- 介绍

          DocView mode,可作为主模式也可以作为minor mode,可以用来阅读DVI(ps后缀),PDF,OpenDocument(libreoffice文档),微软的doc.支持截取 ...

  10. 关于Linux下使用expdp和impdp命令对Oracle数据库进行导入和导出操作

    说明:本次导入和导出采用expdp和impdp命令进行操作,这2个命令均需要在服务器端进行操作 http://www.cnblogs.com/huacw/p/3888807.html 一.    从O ...