题目描述

  • 题意就是把一个四位的质数转化为另一个四位的质数,每次只能改变一位数字,且改变后仍要是质数,问最少需要多少次转化
    一开始代码写的很粗糙
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream>
#include <string.h>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

const int N = 10000;
bool a[N + 1];
vector<int> prime;
void get_prime() {
memset(a, true, sizeof(a));
for (int i = 2; i <= N; i++) {
if (a[i]) prime.push_back(i);
for (int j = 0; j < prime.size() && i * prime[j] <= N; j++) {
a[i * prime[j]] = false;
if (i % prime[j]==0) break;
}
}
}

struct Node{
int number;
int money;
};

queue<Node>qu;
int start,ended;
int vis[N] = {0};
void bfs()
{
int bit,i,j,k,temp;
Node first_node;
Node temp_node;
Node now_node;

first_node.number = start;
first_node.money = 0;
qu = queue<Node>();
qu.push(first_node);
memset(vis,0,sizeof(vis));
while(!qu.empty()) {
now_node = qu.front();
if (now_node.number == ended) {
cout << now_node.money << endl;
return;
}
temp = now_node.number;
for (i = 0; i < 3; i++) { //个位十位百位
bit = temp%10;
for (j = bit + 1, k = 1; j < 10; j++, k++) { //增大
if (a[now_node.number + k * (int) pow(10, i)] && !vis[now_node.number + k * (int) pow(10, i)]) {
temp_node.number = now_node.number + (int) k * pow(10, i);
temp_node.money = now_node.money + 1;
vis[temp_node.number] = 1;
qu.push(temp_node);
}
}
for (j = bit - 1, k = 1; j >= 0; k++, j--) { /*减小*/
if (a[now_node.number - k * (int) pow(10, i)] && !vis[now_node.number - k * (int) pow(10, i)]) {
temp_node.number = now_node.number - (int) k * pow(10, i);
temp_node.money = now_node.money + 1;
vis[temp_node.number] = 1;
qu.push(temp_node);
}
}
temp/=10;
}
/*千位*/
bit = temp%10;
for (j = bit + 1, k = 1; j < 10; j++, k++){
if (a[now_node.number + 1000 * k] && !vis[now_node.number + 1000 * k]) {
temp_node.number = now_node.number+1000*k;
temp_node.money = now_node.money+1;
vis[temp_node.number] = 1;
qu.push(temp_node);
}
}
for (j = bit - 1, k = 1; j > 0; j--, k++) {
if (a[now_node.number - 1000 * k] && !vis[now_node.number - 1000 * k]) {
temp_node.number = now_node.number - 1000 * k;
temp_node.money = now_node.money + 1;
vis[temp_node.number] = 1;
qu.push(temp_node);
}
}
qu.pop();
}
}

int main() {
int k,i;

get_prime();
cin>>k;
for(i=0;i<k;i++){
cin>>start>>ended;
bfs();
}
return 0;
}

转化的过程写的十分繁琐
于是学习了http://www.cnblogs.com/liuxin13/p/4648717.html
的代码
搬运一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <queue>

#define maxn 10000
using namespace std;

int p[maxn];

int Prime(int n)
{
int i,k=sqrt(n);

for(i=2;i<=k;i++) {
if (n % i == 0)
return 0;
}
return 1;
}

int Turn(int n,int k)
{
char s[10] = {0};

sprintf(s,"%d",n);
s[k] = '0';
sscanf(s,"%d",&n);
return n;
}

int BFS(int s,int e)
{
int i,j,k,q;
int v[maxn] = {0};
queue<int> Q;

Q.push(s);
v[s] = 1;
while(!Q.empty()){
s = Q.front();
if(s==e)
return v[s] - 1;
int t=1000;
for(i=0;i<4;i++){
q = Turn(s,i);
for(k=0;k<10;k++){
j=q+k*t;
if(p[j]==1 && v[j]==0){
Q.push(j);
v[j] = v[s]+1;
}
}
t/=10;
}
Q.pop();
}
return -1;
}

int main() {
int i,s,e,T,ans;

for(i=1000;i<maxn;i++)
p[i] = Prime(i);
scanf("%d",&T);
while(T--){
scanf("%d%d",&s,&e);
ans = BFS(s,e);
if(ans==-1)
printf("Impossible\n");
else
printf("%d\n",ans);
}
return 0;
}
  • Turn()中先利用sprintf()把int型变量n写到字符数组s中,然后把s的第k位设为’0’,再用ssprintf()把s转化为整形,从而实现转化
  • 求质数表可以用我一开始那段代码的线筛,效率更高