原题链接:
http://poj.org/problem?id=3126
题目大意:
先输入一个n(n不超过100)。表示有n组的测试样例。然后输入两个素数。第一个表示起始数。第二个表示目标数。问要多少是操作才可以把第一个数变成第二个数。
操作要求:
1.每次操作后的数必须是素数
2.每次操作只能改动一个数字
如果可以输出需要多少次。不行输出“Impossible”
思路:
采用一种笨办法:
从-9~9每个计算过去小于0或者大于9都舍去。然后判断是不是素数
其他的和一般的BFS类似
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
int T;
int Start,End;
int Check[10005];
int Pre[10005];
int number;
int Change[18]={-9,-8,-7,-6,-5,-4,-3,-2,-
1,1,2,3,4,5,6,7,8,9};
bool Find;
bool is_prime(int n)
{
int result = 0;
int i;
if (n <= 1)
{
return result;
}
if(2 == n)
{
result = 1;
return result;
}
for (i = 2; i < n ;i++)
{
if (0 == n % i)
{
result = 0;
break;
}
else if (i + 1 == n)
{
result = 1;
}
else
{
continue;
}
}
return result;
}
void GetCount( int Index )
{
while( Pre[Index] != -1 )
{
Index = Pre[Index];
number++;
}
}
bool IsNumberLeagal( int x )
{
if( x < 0 || x > 9 )
return false;
return true;
}
bool IsLeagal( int Index )
{
if( Index < 1000 || Index > 9999 )
return false;
return true;
}
void bfs()
{
queue<int> Path;
memset( Check,0,sizeof( Check ) );
memset( Pre,0,sizeof( Pre ) );
Check[Start] = 1;
Pre[Start] = -1;
Path.push ( Start );
int Now,Next,fir,sec,thr,fou;
int i,nfir,nsec,nthr,nfou;
while( !Path.empty () )
{
Now = Path.front ();
Path.pop ();
fir = ( Now % 10000 ) /1000;
sec = ( Now % 1000 ) /100;
thr = ( Now % 100 ) /10;
fou = ( Now % 10 ) /1;
for( i = 0; i < 18; i++ )
{
nfir = fir + Change[i];
if( !IsNumberLeagal( nfir ) )
continue;
Next = nfir *1000 + sec *100 + thr
*10 + fou *1;
if( IsLeagal( Next ) && !Check
[Next] && is_prime( Next ) )
{
Check[Next] = 1;
Pre[Next] = Now;
if( Next == End )
{
Find = true;
GetCount( Next );
return ;
}
Path.push ( Next );
}
}
for( i = 0; i < 18; i++ )
{
nsec = sec + Change[i];
if( !IsNumberLeagal( nsec ) )
continue;
Next = fir *1000 + nsec *100 + thr
*10 + fou *1;
if( IsLeagal( Next ) && !Check
[Next] && is_prime( Next ) )
{
Check[Next] = 1;
Pre[Next] = Now;
if( Next == End )
{
Find = true;
GetCount( Next );
return ;
}
Path.push ( Next );
}
}
for( i = 0; i < 18; i++ )
{
nthr = thr + Change[i];
if( !IsNumberLeagal( nthr ) )
continue;
Next = fir *1000 + sec *100 + nthr
*10 + fou *1;
if( IsLeagal( Next ) && !Check
[Next] && is_prime( Next ) )
{
Check[Next] = 1;
Pre[Next] = Now;
if( Next == End )
{
Find = true;
GetCount( Next );
return ;
}
Path.push ( Next );
}
}
for( i = 0; i < 18; i++ )
{
nfou = fou + Change[i];
if( !IsNumberLeagal( nfou ) )
continue;
Next = fir *1000 + sec *100 + thr
*10 + nfou *1;
if( IsLeagal( Next ) && !Check
[Next] && is_prime( Next ) )
{
Check[Next] = 1;
Pre[Next] = Now;
if( Next == End )
{
Find = true;
GetCount( Next );
return ;
}
Path.push ( Next );
}
}
}
}
int main()
{
cin >> T;
while( T-- )
{
cin >> Start >> End;
if( Start == End )
{
cout<<0<<endl;
continue;
}
number = 0;
Find = false;
bfs();
if( Find )
cout<< number <<endl;
else
cout<< "Impossible" << endl;
}
return 0;
}