SPOJ - Prime Path (PPATH)

SPOJ - Prime Path (PPATH)

本文关键字:PPATH Path Prime SPOJ      更新时间:2023-10-16

我正在尝试解决SPOJ问题"Prime Path":

问题是找到转换4位数字的最简单方法通过将一个一位数更改为另一个4位数的素数并且中间值也是素数。

我正在我的解决方案中进行bfs。在转换函数中,我正在更改数字相应位置的数字。

  1. 数以百计
  2. 数千

我的解决方案代码如下。我在第一个测试用例中得到了错误的答案。如果有人能在我的程序中找到这个错误,我会很高兴。

#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;
}

问题出在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

除了01,所有这些恰好都是素数的平方。

你可以通过改变来解决这个问题

for (int i = 2; i < sqrt(number); i++) {

进入

for (int i = 2; i <= sqrt(number); i++) {

这将使您的函数只错误地返回数字01true,但这对这个特定的问题并不重要。

然而,一个更有效的方法是使用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函数的情况下提交您的代码。可能还有其他问题,但在我看来还可以。你的逻辑和我接受的解决方案是一样的,从我所看到的来看,你没有遗漏任何边缘案例。