#902 素数之欢

现给定两个 四位素数 a,ba,b。 你可以执行多次下面的操作:

修改数字 aa 的某一位, 使其成为另一个 四位素数

例如,1033→17331033→1733,其中 10331033 与 17331733 均为素数。

问至少多少次变换后能从 aa 得到 bb ? 或回答不可能。

数据规模

  • 多组数据 1≤T≤1001≤T≤100

输入格式

第一行一个数字 TT,表示接下来将会有 TT 组数据。

接下来包含 TT 行,每行包含用空格分开的两个 四位素数 a,ba,b。

输出格式

输出 TT 行,如果可以,输出最小变换次数。反之输出 −1−1。

样例输入

2
1033 1033
1033 8779

样例输出

0
5

说明

1033→1733→3733→3739→3779→87791033→1733→3733→3739→3779→8779


tips: you only operate 88 times if possible.

这一题可以使用bfs,首先将四位数的素数提取出来,用map存储,将其看成一个无向图,且边权为1,然后使用bfs,在个位,十位,百位,千位,改变一个位数的数,判断这个数是否已经进队并且判断是否是素数,然后如果都合格,就入队,然后继续bfs,直到找到第一个答案,因为bfs第一个找到的答案一定是最优解,直接输出。

一开始我还在想贪心,然后实在贪心不出来,就去看题解,经过sls大佬,我明白了这个可以遍历找到答案的题目可以使用bfs。

代码如下:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e5 + 50, MOD = 1e8 - 7;

bool prime(int num)
{
    if (num == 2 || num == 3)
        return true;
    if (num % 6 != 1 && num % 6 != 5)
        return false;

    int temp;
    temp = int(sqrt(float(num)));
    for (int i = 5; i <= temp; i += 6)
    {
        if (num % i == 0 || num % (i + 2) == 0)
            return false;
    }
    return true;
}

map<ll, ll>mp;
ll st[N];
ll arr[N];
void bfs(ll x,ll y)
{
    map<ll, ll>mymp;
    memset(st, 0, sizeof(st));
    queue<ll>q;
    q.push(x);
    mymp[x] = 0;
    st[x] = 1;
    while (q.size())
    {
        auto u = q.front(); q.pop();
        /*cout <<  "u :" << u << "mp[u]" << mymp[u] << "\n";*/
        if (u == y)
        {
            cout << mymp[u] << "\n";
            return;
        }
        ll a = u % 10;
        ll b = (u / 10) % 10;
        ll c = (u / 100) % 10;
        ll d = u / 1000;

        for (int i = 1; i <= 9; i++)
        {
            if (i == a)continue;
            ll num = i + 10 * b + 100 * c + 1000 * d;
            if (mp[num] && !st[num])q.push(num), mymp[num] = mymp[u] + 1,st[num] = 1;
        }

        for (int i = 0; i <= 9; i++)
        {
            if (i == b)continue;
            ll num = a + 10 * i + 100 * c + 1000 * d;
            if (mp[num] && !st[num])q.push(num), mymp[num] = mymp[u] + 1, st[num] = 1;
        }
        for (int i = 0; i <= 9; i++)
        {
            if (i == c)continue;
            ll num = a + 10 * b + 100 * i + 1000 * d;
            if (mp[num] && !st[num])q.push(num), mymp[num] = mymp[u] + 1, st[num] = 1;
        }

        for (int i = 0; i <= 9; i++)
        {
            if (i == d)continue;
            ll num = a + 10 * b + 100 * c + 1000 * i;
            if (mp[num] && !st[num])q.push(num), mymp[num] = mymp[u] + 1, st[num] = 1;
        }

    }
    cout << -1 << "\n";
}

void work()
{
    ll a, b;
    cin >> a >> b;
    bfs(a, b);
}
int main()
{
    for (int i = 1000; i <= 9999; i++)
    {
        if (prime(i))mp[i] = 1;
    }
    /*for (int i = 1000; i <= 9999; i++)
    {
        if (mp[i])cout << i << "\n";
    }*/
    ll t;
    cin >> t;
    while (t--)
    {
        work();
    }

    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值