ZOJ Problem Set - 4020 Traffic Light
题意
在道路上从a到b, 每一个十字路口都有红绿灯,红绿灯的状态有开关两种,每走一次变一下,在不同的状态可以往不同的方向走,求最短路径(和最短路径一个意思)
分析
本体的关键就是要知道经过一个点之后,一定不会再回来,因为回来的时候和现在红绿的状态一样,即回到远来的位置一定是偶数步,所以走回来就没有意义了。 所以怎么解这道题呢,当然是广搜,把所有能走到的节点加进去,最后如果搜不到就是“No Solution” ,否则输出时间
参考代码
#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int prime = 999983;
const int INF = 0x7FFFFFFF;
const LL INFF =0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
const int maxn = 1e5+100;
int State[maxn];
bool vis[maxn];
int n,m;
int X1,Y1,x2,y2;
struct T{
int x,y,t;
T(int xx,int yy,int tt):x(xx),y(yy),t(tt){}
};
int bfs()
{
queue<T> q;
q.push(T(X1,Y1,0));
vis[X1*m+Y1] = 1;
while(!q.empty())
{
T a = q.front(); q.pop();
if(a.x == x2&&a.y == y2)// 如果找到,返回到这个点的时间
return a.t;
int x = a.x,y = a.y,t = a.t;
int s = (t&1?!State[x*m+y]:State[x*m+y]);// 判断奇数步和偶数步确定状态以确定 行进方向
if(s)
{
for(int i = 2;i < 4; ++i)
{
int R = x + dr[0][i];
int C = y + dr[1][i];
if(R < n&&R >= 0&&C < m&&C >=0&&!vis[R*m+C])
{
vis[R*m+C] = true;
q.push(T(R,C,t+1));// 注意时间要+1
}
}
}
else
{
for(int i = 0;i < 2; ++i)
{
int R = x + dr[0][i];
int C = y + dr[1][i];
if(R < n&&R >= 0&&C < m&&C >= 0&&!vis[R*m+C])
{
vis[R*m+C] = true;
q.push(T(R,C,t+1));
}
}
}
}
return -1;
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--)
{
memset(vis,0,sizeof(vis));
scanf("%d %d",&n,&m);
for(int i = 0;i < n; ++i)
{
for(int j = 0;j < m; ++j)
{
scanf("%d",&State[i*m+j]);
}
}
scanf("%d %d %d %d",&X1,&Y1,&x2,&y2);
X1--,Y1--,x2--,y2--;
printf("%d\n",bfs());
}
return 0;
}