题意:给定两个素数 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; }