poj 3126(写的有点乱,简单的多入口bfs)

题目的大意就是,给出两个四位素数n,m,每次只改变n一个数位上面的数字使他成为另外一个素数,要求从n变到m的最短路径。

由于是最短路径问题,所以很明显采取的做法是通过bfs。
  • 哎,写这个题目的时候没有管数据范围,以为很大就又是快筛,又是二分,写完发现根本没必要,反正也懒得改了就这样了。关键是这个题目不是从2开始的,快速筛不好写,为了警戒自己就还是发上来了。
//#include<bits/stdc++.h> // poj的日常不能用的头文件
#include<queue>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e5+7;
typedef long long ll;
bool isprime[N],que[N]; // que数组用来存储已搜索的数字
int prime[N],sum[4]; // prime数组来存储素数,而sum数组用来存储数位
int cnt=0,n,m; // cnt用来存储素数个数方便后面的二分查找(很显然这个完全没有必要)
struct node{
    int num,step;
}; // 这个结构体num是为了存储该次变化,而step是用来存储以变化次数
/*void fast_find_prime() // 写low了的快筛
{
    memset(isprime,true,sizeof isprime);
    for(int i = 2;i < 1e4;++i){
        if(isprime[i]) prime[++cnt] = i;
        for(int j = 1;j < cnt && prime[j] * i < 1e4;++j)
            isprime[prime[j] * i] = false;
    }
}*/
void find_prime() // 筛选素数
{
    for(int i = 1009;i <= 1e4;++i){
        bool flag = true;
        for(int j = 2;j <= sqrt(i);++j){
            if(i % j == 0){
                flag = false;
                break;
            }
        }
        if(flag) prime[++cnt] = i;
    }
}
bool judge_fast_find(int p) // 通过二分查找来判断该种变化是否为素数
{
    int l = 1,r = cnt,mid;
    while(r - l > 1){
        mid = (l + r) / 2;
        if(p > prime[mid]) l = mid;
        else r = mid;
    }
    if(p == prime[l] || p == prime[r]) return true;
    return false;
}
bool judge(int i,int j,node &res,int v) // 判断该次变化是否符合题意
{
    sum[0] = v / 1000;
    sum[1] = v % 1000 / 100;
    sum[2] = v % 100 / 10;
    sum[3] = v % 10;
    sum[i] = j; // 进行数位变化
    int t = 1000 * sum[0] + 100 * sum[1] + 10 * sum[2] + sum[3]; // 计算出新数
    if(!que[t] && judge_fast_find(t)){
        res.num = t; // 通过引用改变数字
        que[t] = true; // 若可行就打上标记
        return true;
    }
    return false;
}
int bfs()
{
    queue<node> q; // 进行判断的队列
    node res; // 用于搜索判断的结构体
    res.num = n,res.step = 0;
    que[n] = true;
    q.push(res);
    while(!q.empty()){
        res = q.front();
        int v = res.num;
        if(res.num == m) return res.step;
        res.step++;
        for(int i = 0;i < 4;++i){
            for(int j = 0;j < 10;++j){
                if(judge(i,j,res,v)){
                    if(res.num == m) return res.step;
                    q.push(res);
                }
            }
        }
        q.pop();
    }
    return -1;
}
int main()
{
    int t;
    cin >> t;
    // fast_find_prime();
    find_prime();
    while(t--){
        cin >> n >> m;
        memset(que,false,sizeof que);
        int ans = bfs();
        // for(int i = 1;i <= cnt;++i) cout << prime[i] <<endl;
        if(ans == -1) cout << "Impossible" << endl;
        else cout << ans <<endl;
    }
    return 0;
}

写到这里,突然发现快筛完全ok。。。

//#include<bits/stdc++.h>
#include<queue>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e5+7;
typedef long long ll;
bool isprime[N],que[N];
int prime[N],sum[4];
int cnt=0,cnf = 0,n,m; // cnf存储第一个四位素数的位置
struct node{
    int num,step;
};
void fast_find_prime()
{
    memset(isprime,true,sizeof isprime);
    for(int i = 2;i < 1e4;++i){
        if(isprime[i]) prime[++cnt] = i;
        if(prime[cnt] == 1009) cnf = cnt;
        for(int j = 1;j < cnt && prime[j] * i < 1e4;++j)
            isprime[prime[j] * i] = false;
    }
}

bool judge_fast_find(int p)
{
    int l = cnf,r = cnt,mid;
    while(r - l > 1){
        mid = (l + r) / 2;
        if(p > prime[mid]) l = mid;
        else r = mid;
    }
    if(p == prime[l] || p == prime[r]) return true;
    return false;
}
bool judge(int i,int j,node &res,int v)
{
    sum[0] = v / 1000;
    sum[1] = v % 1000 / 100;
    sum[2] = v % 100 / 10;
    sum[3] = v % 10;
    sum[i] = j;
    int t = 1000 * sum[0] + 100 * sum[1] + 10 * sum[2] + sum[3];
    if(!que[t] && judge_fast_find(t)){
        res.num = t;
        que[t] = true;
        return true;
    }
    return false;
}
int bfs()
{
    queue<node> q;
    node res;
    res.num = n,res.step = 0;
    que[n] = true;
    q.push(res);
    while(!q.empty()){
        res = q.front();
        int v = res.num;
        if(res.num == m) return res.step;
        res.step++;
        for(int i = 0;i < 4;++i){
            for(int j = 0;j < 10;++j){
                if(judge(i,j,res,v)){
                    if(res.num == m) return res.step;
                    q.push(res);
                }
            }
        }
        q.pop();
    }
    return -1;
}
int main()
{
    int t;
    cin >> t;
    fast_find_prime();
    while(t--){
        cin >> n >> m;
        memset(que,false,sizeof que);
        int ans = bfs();
        // for(int i = 1;i <= cnt;++i) cout << prime[i] <<endl;
        if(ans == -1) cout << "Impossible" << endl;
        else cout << ans <<endl;
    }
    return 0;
}
因为其他的都差不多,就不一一注释了。。。很迷,居然就快了1ms,没意思
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值