0623搜索专题-F题

题目描述:

 

 读完题目大家有思路了吗?反正我有了:哪个**闲的没事干这b玩意,****。

整体思路算是比较暴力,就是将这个四位数的每一位都拆解开来,让每位都从0-9挨个换一遍,组成一个新的数字再将其判断是否为质数。

一个小坑:任意数字的首位不得为0,代码里特判一下就好。

想到这,思路就很清晰了,大概是一个筛质数+拆分数字+组合数字,因为题目要求是最小次数,所以就bfs直接搜索就行。

贴上代码:

  #include <cstring>
  #include <queue>
  #include <string>
  #include <iostream>
  #include <map>
  const int N = 100005;
  int not_prime[N], a[10], vis[N], step[N];
  
  void get_prime() {//质数筛
  not_prime[0] = 1;
  not_prime[1] = 1;
  for (int i = 2; i < N; i++) {
    if (!not_prime[i]) {
    for (int j = 2 * i; j < N; j += i) {
      not_prime[j] = true;
      }
    }
  }
}

  void solve() {
  memset(vis, 0, sizeof vis);
  memset(vis, 0, sizeof vis);
  memset(step, 0, sizeof step);
  std::queue<int> q;
  int s, t; // 起始数字和目标数字
  std::cin >> s >> t;
  q.push(s);
  vis[s] = 1;
  while (!q.empty()) {//正常bfs队列
  int f = q.front();
  q.pop();
  if (f == t) {
  break;
  }
  int tf = f;
  for (int i = 3; i >= 0; i--) { // 为了把数字f拆分成数位
  // 1123
  // a[0] = 1, a[1] = 1, a[2] = 2, a[3] = 3;
  a[i] = f % 10;
  f /= 10;
  }
  f = tf;
  for (int i = 0; i < 4; i++) { // 枚举每一个数位,a[0], a[1], a[2], a[3]
  int backup = a[i]; // 记录一下原来a[i]是什么数字
  for (int j = 0; j < 10; j++) { // 枚举把a[i]这个数位变成什么数字
  a[i] = j; // 把第i位变成j
  int tt = 0; // 把第i位变成j之后,这个数字是什么
  for (int k = 0; k < 4; k++) {
  tt = tt * 10 + a[k];//重新组合
  }
  if (tt >= 1000 && !not_prime[tt] && !vis[tt]) {
    // 首位是不是0,tt是不是质数,tt之前有没有被访问过
    step[tt] = step[f] + 1;
    // step[tt] 表示从起始数字s到数字tt需要几步变换
    vis[tt] = 1;
    q.push(tt);
      }
  }
  a[i] = backup; // 把a[i]原来的数字恢复回去
  }
}
  if (!vis[t]) std::cout << "Impossible" << '\n';
  else std::cout << step[t] << '\n';
 }

  int main() {
  // freopen("in.txt", "r", stdin);
  get_prime();
  int T;
  std::cin >> T;
  while (T--) {
  solve();//直接写在solve里方便整理,不会那么的乱
  }
  return 0;
 }

posted @ 2023-07-03 15:28  yr&jy  阅读(8)  评论(0)    收藏  举报