/*
translation:
给出一个4位素数,要将其转化为另外一个指定的素数。每次只能改变其中一位数字,且期间所有的数字全为素数。
问最少要经过多少步骤?
solution:
埃氏筛法,双向bfs
打个表,再广搜一下即可,水题。为了提高下难度,所以改用双向广搜。0ms过!
note:
date:
2016.10.28
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 10000;
char s[5], t[5];
bool not_prime[maxn];
int dist[maxn], color[maxn];
void init()
{
memset(not_prime, 0, sizeof(not_prime));
not_prime[0] = not_prime[1] = true;
for(int i = 2; i*i <= 10000; i++) if(!not_prime[i])
for(int j = i*i; j <= 10000; j += i) not_prime[j] = true;
}
int d_bfs()
{
queue<int> fq; //正向搜索队列
queue<int> bq; //反向搜索队列
memset(dist, 0, sizeof(dist));
memset(color, 0, sizeof(color));
dist[atoi(s)] = 0; dist[atoi(t)] = 1;
color[atoi(s)] = 1; color[atoi(t)] = 2;
fq.push(atoi(s));
bq.push(atoi(t));
while(!fq.empty() || !bq.empty()){
int fcnt = fq.size(), bcnt = bq.size();
//printf("&%d %d\n", fcnt, bcnt);
while(fcnt--){
int x = fq.front(); fq.pop();
char dup[5], tmp[5];
sprintf(tmp, "%d", x);
for(int i = 0; i < 4; i++){
for(int j = 0; j < 10; j++){
if(i == 0 && j == 0) continue;
memcpy(dup, tmp, sizeof(tmp));
dup[i] = j + '0';
int m = atoi(dup);
if(color[m] == 0 && !not_prime[m]){
color[m] = 1;
dist[m] = dist[x] + 1;
fq.push(m);
}
else if(color[m] == 2) return dist[m] + dist[x];
}
}
}
while(bcnt--){
int x = bq.front(); bq.pop();
char dup[5], tmp[5];
sprintf(tmp, "%d", x);
for(int i = 0; i < 4; i++){
for(int j = 0; j < 10; j++){
if(i == 0 && j == 0) continue;
memcpy(dup, tmp, sizeof(tmp));
dup[i] = j + '0';
int m = atoi(dup);
//printf("#%s %d color:%d prime:%d\n", dup, m, color[m], not_prime[m]);
if(color[m] == 0 && !not_prime[m]){
color[m] = 2;
dist[m] = dist[x] + 1;
bq.push(m);
}
else if(color[m] == 1) return dist[m] + dist[x];
}
}
}
}
return -1;
}
int main()
{
//freopen("in.txt", "r", stdin);
init();
int T;
scanf("%d", &T);
while(T--){
scanf("%s%s", s, t);
if(atoi(s) == atoi(t)) cout << 0 << endl;
else cout << d_bfs() << endl;
}
return 0;
}
这道题当然也可以用普通bfs,代码如下,运行时间110ms
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 10000;
char s[5], t[5];
bool not_prime[maxn], vis[maxn];
struct Node
{
int val, d;
Node(int val, int d):val(val),d(d){}
Node(){}
};
void init()
{
memset(not_prime, 0, sizeof(not_prime));
not_prime[0] = not_prime[1] = true;
for(int i = 2; i*i <= 10000; i++) if(!not_prime[i])
for(int j = i*i; j <= 10000; j += i) not_prime[j] = true;
}
int bfs()
{
queue<Node> q;
memset(vis, 0, sizeof(vis));
q.push(Node(atoi(s), 0));
while(!q.empty())
{
Node x = q.front(); q.pop();
char tmp[10];
sprintf(tmp, "%d", x.val);
//printf("#%s\n", tmp);
if(vis[x.val]) continue;
vis[x.val] = true;
if(x.val == atoi(t)) return x.d;
char dup[10];
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 10; j++)
{
memcpy(dup, tmp, sizeof(tmp));
if(i == 0 && j == 0) continue;
dup[i] = '0' + j; //printf("$%s\n", dup);
int res = atoi(dup);
if(vis[res] || not_prime[res]) continue;
q.push(Node(res, x.d+1));
}
}
}
return -1;
}
int main()
{
//freopen("in.txt", "r", stdin);
init();
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s%s", s, t);
if(atoi(s) == atoi(t)) cout << 0 << endl;
else cout << bfs() << endl;
}
return 0;
}