题意:给定两个素数 a, b (均为四位数),要求将素数 a 修改成素数 b,每次只能修改一个位置上的数字,且中间的每一步得到的数字也必须是素数。求最少需要的步骤数。若不能将 a 按规定要求换成 b,则输出Impossible.
题解:给出两组代码。
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
#define N 10000
int step[N];
bool vis[N], prime[N];
void getPrime ()
{
memset(prime,-1,sizeof(prime));
prime[0] = prime[1] = 0;
for ( int i = 2; i <= 100; i++ )
{
if ( prime[i] )
for ( int j = 2; i * j < N; j++ )
prime[i*j] = 0;
}
}
int bfs( int a, int b )
{
memset(vis,0,sizeof(vis));
memset(step,0,sizeof(step));
queue<int> Q;
vis[a] = true;
Q.push(a);
int cur, bit, temp, newNum, i;
while ( !Q.empty() )
{
cur = Q.front(); Q.pop();
if ( cur == b )
return step[cur];
bit = cur % 10; // 修改个位
for ( i = -9; i <= 9; i++ )
{
temp = bit + i;
if ( temp >= 0 && temp <= 9 && temp != bit )
{
newNum = ( cur / 10 ) * 10 + temp;
if ( prime[newNum] && ! vis[newNum] )
{
step[newNum] = step[cur] + 1;
vis[newNum] = 1;
Q.push(newNum);
}
}
}
bit = cur / 10 - cur / 100 * 10; //修改十位
for ( i = -9; i <= 9; i++ )
{
temp = bit + i;
if ( temp >= 0 && temp <= 9 && temp != bit )
{
newNum = ( cur / 100 ) * 100 + temp * 10 + cur % 10;
if ( prime[newNum] && ! vis[newNum] )
{
step[newNum] = step[cur] + 1;
vis[newNum] = 1;
Q.push(newNum);
}
}
}
bit = cur / 100 - cur / 1000 * 10; //修改百位
for ( i = -9; i <= 9; i++ )
{
temp = bit + i;
if ( temp >= 0 && temp <= 9 && temp != bit )
{
newNum = ( cur / 1000 ) * 1000 + temp * 100 + cur % 100;
if ( prime[newNum] && !vis[newNum] )
{
step[newNum] = step[cur] + 1;
vis[newNum] = 1;
Q.push(newNum);
}
}
}
bit = cur / 1000; //修改千位
for ( i = -9; i <= 9; i++ )
{
temp = bit + i;
if ( temp > 0 && temp <= 9 && temp != bit )
{
newNum = temp * 1000 + cur % 1000;
if ( prime[newNum] && !vis[newNum] )
{
step[newNum] = step[cur] + 1;
vis[newNum] = 1;
Q.push(newNum);
}
}
}
}
return -1;
}
int main()
{
int t, a, b;
getPrime();
scanf("%d",&t);
while ( t-- )
{
scanf("%d%d",&a,&b);
int res = bfs ( a, b );
if ( res < 0 )
printf("Impossible\n");
else
printf("%d\n",res);;
}
return 0;
}
一开是也想用字符串来处理数字的变化,但是找不到合适的方式。刚刚看了Discuss,发现了sprintf 函数。所以把上面的改了下。
//把整数123 打印成一个字符串保存在s 中。sprintf(s, "%d", 123); //产生"123"
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
#define N 10000
int step[N];
bool vis[N], prime[N];
void getPrime ()
{
memset(prime,-1,sizeof(prime));
prime[0] = prime[1] = 0;
for ( int i = 2; i <= 100; i++ )
{
if ( prime[i] )
for ( int j = 2; i * j < N; j++ )
prime[i*j] = 0;
}
}
int bfs( int a, int b )
{
memset(vis,0,sizeof(vis));
memset(step,0,sizeof(step));
queue<int> Q;
vis[a] = true;
Q.push(a);
int cur,newNum;
while ( ! Q.empty() )
{
cur = Q.front();
Q.pop();
if ( cur == b )
return step[cur];
for ( int i = 0; i < 4; i++ )
{
char num[5];
sprintf(num,"%d",cur);
for ( int j = 0; j < 10; j++ )
{
if ( j == 0 && i == 0 ) continue;
switch ( i )
{
case 0: newNum=j*1000+(num[1]-'0')*100+(num[2]-'0')*10+(num[3]-'0'); break;
case 1: newNum=j*100+(num[0]-'0')*1000+(num[2]-'0')*10+(num[3]-'0'); break;
case 2: newNum=j*10+(num[0]-'0')*1000+(num[1]-'0')*100+(num[3]-'0'); break;
case 3: newNum=j+(num[0]-'0')*1000+(num[1]-'0')*100+(num[2]-'0')*10; break;
}
if ( prime[newNum] && !vis[newNum] )
{
step[newNum] = step[cur]+1;
vis[newNum] = true;
Q.push ( newNum );
}
}
}
}
return -1;
}
int main()
{
int n, a, b;
getPrime();
scanf("%d",&n);
while ( n-- )
{
scanf("%d%d",&a,&b);
int res = bfs( a, b );
if ( res < 0 )
printf("Impossible\n");
else
printf("%d\n",res);
}
return 0;
}