我正在尝试解决SPOJ问题“Prime Path”:
问题是找到转换4位数的最不可能的方法 通过改变一位数将素数改为另一个4位素数 一次,中间值也是素数。
我在我的解决方案中正在做一个bfs。在转换功能中,我正在更改数字的相应位置中的数字。
我的解决方案代码如下。我在第一个测试用例本身得到了错误的答案。如果有人能在我的程序中找到错误,我会很高兴。
#include<bits/stdc++.h>
// My Terms
#define pb push_back
#define mp make_pair
#define ins insert
#define fir first
#define sec second
#define PRINT(x) cout << #x << " " << x << endl
#define pi acos(-1)
#define ll long long
#define EM empty()
#define sz(a) int((a).size())
#define all(c) (c).begin(),(c).end()
#define fill(a,v) memset(a, v, sizeof(a))
using namespace std;
unsigned long long mod=1000000007;
bool isprime(int number) {
for (int i = 2; i < sqrt(number); i++) {
if (number % i == 0 && i != number) return false;
}
return true;
}
long long convert(long long num,int position ,int value) // position is ones tens hundreds etc
{
int ones=num%10;num/=10;
int tens=num%10;num/=10;
int hunderds=num%10;num/=10;
int thousands=num%10;num/=10;
if(position==1)
{
return ( (thousands*1000) +(hunderds*100) + (tens*10) + (value) );
}
else if (position==2)
{
return ( (thousands*1000) +(hunderds*100) + (value*10) + (ones) );
}
else if (position==3)
{
return ( (thousands*1000) +(value*100) + (tens*10) + (ones) );
}
else if (position==4)
{
return ( (value*1000) +(hunderds*100) + (tens*10) + (ones) );
}
}
int n;long long l,m;
int main()
{
cin>>n;
while(n)
{
cin>>l>>m;
long long level=0;
queue< pair< int,int > > q;
q.push(make_pair(l,0) );
int visited[10010]={0};
visited[l]=1;
int flag=0;
while(q.size())
{
l=q.front().first;
level=q.front().second;
q.pop();
if(l==m)
{
cout<<level<<"\n";
flag=1;
break;
}
//cout<<l<<" "<<level <<"\n";
for(int i=0;i<=9;i++)
{
/////////////////////////////
// for thousands's place digit
if(i>0)
{
long long a2=convert(l,4,i);
if( visited[a2]!=1 && isprime(a2) )
{
q.push( make_pair( a2,level+1 ) );
visited[a2]=1;
}
}
//////////////////////////////////
// for hunderd's place digit
long long b2=convert(l,3,i);
if( visited[b2]!=1 && isprime(b2) )
{
//cout<<a2<<"\n";
q.push( make_pair( b2,level+1 ) );
visited[b2]=1;
}
////////////////////////////
// for ten's place digit
long long c2=convert(l,2,i);
if( visited[c2]!=1 && isprime(c2) )
{
q.push( make_pair( c2,level+1 ) );
visited[c2]=1;
}
////////////////////////////
// for one's place digit
long long d2=convert(l,1,i);
if( visited[d2]!=1 && isprime(d2) )
{
//cout<<a2<<"\n";
q.push( make_pair( d2,level+1 ) );
visited[d2]=1;
}
}
}
if(flag==0)
{
cout<<"Impossible"<<"\n";
}
n--;
}
return 0;
}
答案 0 :(得分:3)
问题在于您的isprime
功能。它错误地返回true
以获取以下数字:
0,1,4,9,25,49,121,169,289,361,529,841,961,1369,1681,1849,2209,2809,3481,3721,4489,5041,5329,6241 ,6889,7921,9409
除了0
和1
之外,所有这些都恰好是素数的平方。
您可以通过更改
来解决此问题for (int i = 2; i < sqrt(number); i++) {
到
for (int i = 2; i <= sqrt(number); i++) {
这会使您的函数仅对数字true
和0
错误地返回1
,但这与此特定问题无关。
然而,更有效的方法是使用Sieve of Eratosthenes。这是一个代码示例。
std::vector<bool> sieve(int largest)
{
std::vector<bool> is_prime(largest+1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i <= largest; ++i) {
if (is_prime[i]) {
for (int j = 2*i; j <= largest; j += i) {
is_prime[j] = false;
}
}
}
return is_prime;
}
然后你可以简单地使用is_prime[number]
进行O(1)查找。
免责声明:我没有尝试在修复isprime
功能的情况下提交您的代码。可能还有其他问题,但对我来说似乎没问题。你的逻辑与我接受的解决方案是一样的,从我看到的你不会错过任何边缘情况。