Problem Description
小莹莹被困在了一个由 n 个石柱围成一圈组成的迷宫里,也就是 1, 2, 3, … n, 1, 2, 3, …. 这样一直循环。
她起始位置是 1,每次只能沿着顺时针方向选择飞跃 a 或者 b 距离的魔法,也就是从当前石柱 i 飞往 i+a 石柱或者 i+b 石柱。
第 m 个石柱有传送门,她只有到达第 m 个石柱,才能从这个迷宫逃脱出去。
问你小莹莹能否能顺利的逃离迷宫,如果不能输出 “NO”.
如果能输出 “YES”,同时问你小莹莹最少需要使用几次魔法?
Input
第一行输入正整数 T 代表有 T 组测试数据。
对于每一组测试数据:
第一行输入由空格隔开的 n, m 代表石柱的数量和所需到达的石柱。
第二行输入由空格隔开的 a, b 代表两个魔法,一个可以飞跃 a 距离,一个可以飞跃 b 距离。
( 1 <= n <= 1e5, 0 <= a, b < n, 1 <= m <= n, T 组数据 n 的和 <= 5e6 )
Output
如果小莹莹顺利逃离迷宫:
第一行输出:”YES”
第二行输出:小莹莹最少使用魔法次数。
如果小莹莹无法逃离迷宫:
第一行输出:”NO”
答案不包含 “”。
Sample Input
3
8 6
2 3
4 3
4 3
4 4
2 2
Sample Output
YES
2
YES
2
NO
Hint
Source
Satw_zg
#include <bits/stdc++.h>
using namespace std;
int bfs(int a, int b, int c, int d, int e);
const int maxn = 100010;
int cnt[maxn];//每个点到初始位置要几步
bool vis[maxn];//标记该点有没有走过
int main()
{
int t, n, m, a, b;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);//n个柱子,要求到达M;
scanf("%d%d", &a, &b);//每次可以跳跃的距离
int k = bfs(1, m, a, b, n);//n个柱子从一号开始每次跳跃a,或者B,要求到达m
if(k == -1)
{
printf("NO\n");
}
else
{
printf("YES\n%d\n", k);
}
}
return 0;
}
int bfs(int a, int b, int c, int d, int e)
{
memset(vis, 0, sizeof(vis));//先将标记数组初始化为0
queue<int> q;//创建一个队列
vis[a] = true;//将首位置标记为1
cnt[a] = 0;//首位置到首位置的距离是0
q.push(a);//将首号位置的坐标放进队列
int s, k;
while(!q.empty())
{
s = q.front();
q.pop();
if(s == b)//判断条件,如果跳跃到b点
{
return cnt[b];//返回cnt[b]的值;
}
k = (s + c)%e;//跳跃c
if(k == 0)k = e;
if(!vis[k])
{
q.push(k);
vis[k] = true;
cnt[k] = cnt[s] + 1;
}
k = (s + d)%e;//跳跃d
if(k == 0)k = e;
if(!vis[k])
{
q.push(k);
vis[k] = true;
cnt[k] = cnt[s] + 1;
}
}
return -1;
}