POJ 3126
问最短路径,所以上来就可以考虑BFS
繁杂的部分在具体问题实现细节,借助这道题正好顺手学了线性求素数筛子,模板如下:
for (int i= 2; i<= maxl; ++i){
if (!chk[i]){
prime[tot++]= i;
}
for (int j= 0; j< tot; ++j){
int n_p= i*prime[j];
if (n_p> maxl){
break;
}
chk[n_p]= 1;
if (!(i%prime[j])){
break;
}
}
}
欧拉筛法核心思想就是每个数一定让他的最小素因数筛去
本体代码核心思路就是素数的预处理,以及预先在4位数素数之间建立图关系
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;
const int maxn= 1e4+3;
const int maxp= 1100;
int chk[maxn], prime[maxn];
bool vis[maxp];
int dis[maxp];
int tot= 0, head= 0;
vector<int> G[maxp];
void PrimeInit()
{
memset(chk, 0, sizeof(chk));
for (int i= 2; i< maxn; ++i){
if (!chk[i]){
prime[tot]= i;
chk[i]= tot++;
}
for (int j= 0; j< tot; ++j){
int n_p= i*prime[j];
if (n_p>= maxn){
break;
}
chk[n_p]= -1;
if (!(i%prime[j])){
break;
}
}
}
for (int i= 0; i< tot; ++i){
if (prime[i]> 1000){
head= i;
break;
}
}
int b[4];
int p, dp;
for (int i= head; i< tot; ++i){
p= prime[i];
b[0]= p%10;
p= p/10;
b[1]= p%10;
p= p/10;
b[2]= p%10;
p= p/10;
b[3]= p;
for (int j= 0; j< 4; ++j){
int uk= 9-b[j];
for (int k= 1; k<= uk; ++k){
dp= k;
for (int q= 1; q<= j; ++q){
dp*= 10;
}
p= prime[i]+dp;
if (-1!= chk[p]){
G[i-head].push_back(chk[p]);
G[chk[p]-head].push_back(i);
}
}
}
}
}
int BFS(const int f, const int t)
{
if (f== t){
return 0;
}
int id;
memset(vis, 0, sizeof(vis));
id= chk[f]-head;
vis[id]= 1;
dis[id]= 0;
queue<int> Q;
Q.push(id);
while (!Q.empty()){
id= Q.front();
Q.pop();
int sz= G[id].size();
int v= dis[id]+1;
for (int i= 0; i< sz; ++i){
int p_id= G[id][i];
if (t== prime[p_id]){
return v;
}
p_id-= head;
if (!vis[p_id]){
vis[p_id]= 1;
dis[p_id]= v;
Q.push(p_id);
}
}
}
return -1;
}
int main()
{
int kase, f, t, ans;
scanf("%d", &kase);
PrimeInit();
while (kase--){
scanf("%d %d", &f, &t);
ans= BFS(f, t);
if (-1== ans){
printf("Impossible\n");
}
else {
printf("%d\n", ans);
}
}
return 0;
}