SPOJ - Prime Path(PPATH)

时间:2014-02-27 10:57:29

标签: c++ graph

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

  

问题是找到转换4位数的最不可能的方法   通过改变一位数将素数改为另一个4位素数   一次,中间值也是素数。

我在我的解决方案中正在做一个bfs。在转换功能中,我正在更改数字的相应位置中的数字。

  1. 那些
  2. 几十
  3. 数百
  4. 数千
  5. 我的解决方案代码如下。我在第一个测试用例本身得到了错误的答案。如果有人能在我的程序中找到错误,我会很高兴。

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

1 个答案:

答案 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

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

您可以通过更改

来解决此问题
for (int i = 2; i < sqrt(number); i++) {

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

这会使您的函数仅对数字true0错误地返回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功能的情况下提交您的代码。可能还有其他问题,但对我来说似乎没问题。你的逻辑与我接受的解决方案是一样的,从我看到的你不会错过任何边缘情况。