帮助SPOJ的算法问题

时间:2010-07-10 22:52:09

标签: algorithm

我认为这将是一个有趣的问题:Prime Path

但是......对我来说很难。 我唯一的想法是“用背包问题做点什么”......而且没有其他想法。 你能跟踪我的好方法吗? 这不是任何挑战或大学的家庭作业。我只是想学点东西。

_

好的,但首先,如何找到这个素数?我是否需要找到所有4位素数,将其添加到图表中?

现在我已生成所有素数。

http://pastebin.com/wbhRNRHQ

你能给我一些示例代码来声明邻居列表中的图形构建吗?

8 个答案:

答案 0 :(得分:7)

似乎是一个简单的图形路径查找问题。

将所有4位数素数作为顶点。如果我们可以从一个到另一个,则用边缘连接两个。

现在给出两个,你需要在我们刚刚形成的图中找到它们之间的最短路径。一个简单的BFS(广度优先搜索)就可以做到这一点。

对于有时间限制的比赛编程,您甚至可以对每个可能的素数对路径进行硬编码,并且接近零运行时间!

答案 1 :(得分:4)

构建一个图形,其中节点都是4位数的素数,并且到处都有弧形,两个数字共有三个数字。从那里,它是一个基本的图遍历,用于找到从一个节点到另一个节点的最低成本路径。

答案 2 :(得分:2)

我遇到了一个类似的问题,我必须将一个4位素数1033转换为另一个4位素数3739,最小步数。我能够解决问题,它可能效率不高,但这是相同的工作代码。

下面的代码是用Java编写的

import java.util.*;

public class PrimeNumberProblem {

    public static void main(String... args) {
        System.out.println("Minimum number of steps required for converting 1033 to 3739 are = "
                + getMinSteps(1033, 3739));
    }

    public static int getMinSteps(int a, int b) {
        if (a == b)
            return 0;

        List<Integer> primes = new ArrayList<>();

        // get all the 4 digit prime numbers
        primes = getPrimeNumbers();

        // consists of graph with vertices as all the prime numbers
        Graph graph = addNumbersToGraph(primes);

        // adding edges to the graph vertices
        Graph finalGraph = addWeightToGraph(graph);

        // min number of steps required
        int result = findShortestRoute(finalGraph.getVertex(a), finalGraph.getVertex(b));

        return result;
    }

    private static int findShortestRoute(Vertex source, Vertex dest) {
        if (source.getVertexValue() == dest.getVertexValue())
            return 0;

        // step 1 Initialize the queue. Also Map to store path
        Queue<Vertex> visitedQueue = new LinkedList<>();
        Map<Vertex, Vertex> currentPrevMap = new HashMap<Vertex, Vertex>();

        // step 2 start from visiting S (starting node), and mark it visited, add to queue
        Map<Integer, Boolean> visited = new HashMap<Integer, Boolean>();
        visited.put(source.getVertexValue(), true);
        visitedQueue.add(source);

        int level = 0;
        // step 3 Repeat until queue is empty
        while (!visitedQueue.isEmpty()) {
            // step 4 remove from queue
            Vertex current = visitedQueue.remove();
            if (current.getVertexValue() == dest.getVertexValue()) {
                printPath(source, dest, currentPrevMap);
                return level;
            } else if (current.getAdjacentVertices().size() > 0) {
                level++;
            }
            // step 5 add each of the unvisited neighbour and mark visited
            for (Vertex adjacentVertex : current.getAdjacentVertices()) {
                Integer value = adjacentVertex.getVertexValue();
                if (value == dest.getVertexValue()) {
                    currentPrevMap.put(adjacentVertex, current);
                    printPath(source, dest, currentPrevMap);
                    return level;
                }
                if (visited.get(value) == null) {
                    currentPrevMap.put(adjacentVertex, current);
                    // mark visited and enqueue it
                    visited.put(value, true);
                    visitedQueue.add(adjacentVertex);
                }
            }
        }
        // not found
        System.out.println("Dest vertex not found");
        return -1;
    }

    private static void printPath(Vertex source, Vertex dest, Map<Vertex, Vertex> currentPrevMap) {
        Vertex node = dest;
        System.out.println("Reverse Path from source: " + source.getVertexValue() + " to dest: "
                + dest.getVertexValue());
        while (node != source) {
            System.out.println(node.getVertexValue());
            node = currentPrevMap.get(node);
        }
        System.out.println(source.getVertexValue());
    }

    private static Graph addWeightToGraph(Graph graph) {
        List<Vertex> vertices = graph.getAllVertices();
        for (Vertex i : vertices) {
            for (Vertex j : vertices) {
                if (i.equals(j))
                    continue;

                if (distance(i, j) == 1) {
                    i.getAdjacentVertices().add(j);
                    // i.addEdge(new Edge(i, j, 1));
                }
            }
        }
        return graph;
    }

    private static int distance(Vertex source, Vertex dest) {
        if (source.getVertexValue() == dest.getVertexValue()) {
            return 0;
        }

        char[] numA = extractIntegers(source.getVertexValue());
        char[] numB = extractIntegers(dest.getVertexValue());

        int len1 = numA.length;

        int tracker = 0;

        for (int i = 0; i < len1; i++) {

            if (numA[i] != numB[i]) {
                numA[i] = numB[i];
                tracker++;
                String sA = String.copyValueOf(numA);
                String sB = String.copyValueOf(numB);
                // if we have reached destination
                if (Integer.parseInt(sA) == Integer.parseInt(sB)) {
                    return tracker;
                }
            }

        }
        return tracker;
    }

    private static char[] extractIntegers(int i) {
        char[] arr = Integer.toString(i).toCharArray();
        return arr;
    }

    private static Graph addNumbersToGraph(List<Integer> primes) {
        Graph g = new Graph();
        for (Integer prime : primes) {
            g.addVertex(new Vertex(prime));
        }
        return g;
    }

    private static List<Integer> getPrimeNumbers() {
        List<Integer> fourDigitPrimes = new ArrayList<>();
        fourDigitPrimes.add(1033);
        fourDigitPrimes.add(1733);
        fourDigitPrimes.add(3733);
        fourDigitPrimes.add(3739);

        // for (int i = 1000; i < 9999; i++) {
        // if (isPrime(i))
        // fourDigitPrimes.add(i);
        // }

        return fourDigitPrimes;
    }

    private static boolean isPrime(int i) {

        for (int k = 2; k < Math.sqrt(i); k++) {
            if (i % k == 0)
                return false;
        }

        return true;
    }
}


class Graph {
    public List<Vertex> vertexList = new ArrayList<Vertex>();

    public void addVertex(Vertex V) {
        vertexList.add(V);
    }


    public List getAllAdjacentNodes(Vertex V) {
        return V.getAdjacentVertices();
    }

    public List getAllVertices() {
        return vertexList;
    }

    public Vertex getVertex(int val) {
        Iterator<Vertex> keys = vertexList.iterator();
        while (keys.hasNext()) {
            Vertex v = keys.next();
            if (v.getVertexValue() == val)
                return v;
        }
        return null;
    }
}


class Vertex {
    int value;
    private List<Vertex> adjacentVertices = new ArrayList<Vertex>();

    public Vertex(int v) {
        this.value = v;
    }

    public List<Vertex> getAdjacentVertices() {
        return adjacentVertices;
    }


    public int getVertexValue() {
        return value;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        Vertex vertex = (Vertex) o;

        return value == vertex.value;

    }

    @Override
    public int hashCode() {
        return value;
    }
}

答案 3 :(得分:0)

查看“广度优先搜索”。同样值得注意的是,问题可以同时“从两端”接近(从数字X到Y的链可以反转以获得Y到X,你可以利用它)。预计算素数将避免大量计算。

答案 4 :(得分:0)

我使用可能的主要测试来运行BFS,只需4位数就能很好地运行。同样,只有4位数字,您可能需要使用更严格的方法来生成要比较的所有素数,以便更快地进行素数检查。

答案 5 :(得分:0)

  

你能给我一些示例代码吗?   在邻居列表上声明图构建?

这是广度优先搜索的示例代码

public static final int MAX = 10000;
boolean[] prime = new boolean[MAX];
int[] dist = new int[MAX];

//get digit i [1 to 4] in num
public int getDigit(int num,int i){
    return num % ((int)Math.pow(10, i)) / ((int) Math.pow(10, i-1)); 
}

//set digit i to d
public int setDigit(int num,int i,int d){
    return (num - getDigit(num, i)*(int)Math.pow(10, i-1)) + d * (int)Math.pow(10,i-1);
}

public int bfs(int start,int end){
    Queue<Integer> q = new LinkedList<Integer>();
    q.add(start);
    HashSet<Integer> visited = new HashSet<Integer>();
    visited.add(start);
    dist[start] = 0;
    int x,y,d = 0;
    while (q.size() > 0){
        x = q.poll();
        d = dist[x]; 
        if (x == end) return d;

        for (int i = 1; i < 5; i++) {
            //digit number i
            for (int j = 0; j < 10; j++) {
                //avoid setting last digit
                if (j == 0 && i == 4) continue;
                //set digit number i to j
                y = setDigit(x, i, j);
                if (prime[y] && y != x && !visited.contains(y)){
                    q.add(y);
                    visited.add(y);
                    dist[y] = d + 1;
                }
            }
        }
    }
    return -1;
}

答案 6 :(得分:0)

这是我使用BFS的解决方案,我已经将所有4位素数保存到数组中,因为不需要编写函数来计算素数。我希望它有所帮助

 #include<stdio.h>
 int hash[10000];
 int a,b,ans,level,new_num,count;
 int prime[] = {1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973};
int size = sizeof(prime)/sizeof(prime[0]);
int bfs(int,int);
typedef struct q{
int x, c;
 } queue;
queue qq[10000];

int isprime(int x)
{

   int l,r,m;
 l=m=0; r=size-1;
 while (l <= r)
{
 int m = l + (r-l)/2;
 if (prime[m] == x)
    return 1;
 if (prime[m] < x)
    l = m + 1;
else
     r = m - 1;
 }
  return 0;
 }

 int bfs(int num1,int num2)
 {
 int i,j,k,p,q,n;
  new_num=p=q=0;
  i=0;
  j=1;
  qq[i].x = num1;
  qq[i].c = 0;
  hash[num1] = 1;
  while(i!=j)
  {   n = qq[i].x;
    level = qq[i].c;
    if(n==num2)
    {
        count = level;
          return count;
    }
    level++;
    p = n%1000;
        for(k=1;k<10;k++)
        {  new_num = (k*1000)+ p;
            if(isprime(new_num)&&(new_num!=n)&&(!hash[new_num]))
            {
                hash[new_num] = 1;
                 qq[j].x = new_num;
                 qq[j].c = level;
                  j++;


            }}
        p=q=new_num=0;

     p = n/1000;
        q = n%100;
      for(k=0;k<10;k++)
        {  new_num = (p*1000)+k*100+q;
            if(isprime(new_num)&&(new_num!=n)&&(!hash[new_num]))
            {
               hash[new_num] = 1;
                 qq[j].x = new_num;
                 qq[j].c = level;
                 j++;
                 }}
  p=q=new_num=0;

   p = n/100;
   q = n%10;
   for(k=0;k<10;k++)
        {  new_num = (p*100)+k*10+q;
            if(isprime(new_num)&&(new_num!=n)&&(!hash[new_num]))
            {
                hash[new_num] = 1;
                 qq[j].x = new_num;
                 qq[j].c = level;
                 j++;
                }}
   p=q=new_num=0;
   p   = n/10;
   for(k=0;k<10;k++)
        {  new_num = (p*10)+k;
            if(isprime(new_num)&&(new_num!=n)&&(!hash[new_num]))
            {
                hash[new_num] = 1;
                 qq[j].x = new_num;
                 qq[j].c = level;
                 j++;
                }}
     p=q=new_num=0;
    i++;

     }
     return -1;}


  int main()
   {
    int v,tc;
    setbuf(stdout,NULL);
    scanf("%d",&tc);
    for(v=1;v<=tc;v++)
    {  int i,j;
    a=b=ans=level=new_num=count=0;
    for(i=0;i<10000;i++)
    {qq[i].x=0;
      qq[i].c=0;
      hash[i]=0;}

    scanf("%d%d",&a,&b);

    if(a==b)
    { ans = 0;}
    else
    { ans = bfs(a,b);}
    printf("Case #%d\n", v);
    if(ans==-1)
   {
    printf("Impossible\n");

    }
    else
   {printf("%d\n",ans);}

    }
    return 0;
    }

答案 7 :(得分:0)

我的使用BFS的Python解决方案:

    import queue
    # Class to represent a graph
    class Graph:
        def __init__(self, V):
            self.V = V  # No. of vertices
            self.prime_list = [[] for i in range(V)]
    # function to add an edge to graph
    def addedge(self, V1, V2):
        self.prime_list[V1].append(V2)
        self.prime_list[V2].append(V1)

    def bfs(self, in1, in2):
        visited = [0] * self.V
        que = queue.Queue()
        visited[in1] = 1
        que.put(in1)
        while not que.empty():
            prime_index = que.get()
            i = 0
            while i < len(self.prime_list[prime_index]):
                if not visited[self.prime_list[prime_index][i]]:
                    visited[self.prime_list[prime_index][i]] = visited[prime_index] + 1
                    que.put(self.prime_list[prime_index][i])
                if self.prime_list[prime_index][i] == in2:
                    return visited[self.prime_list[prime_index][i]] - 1
                i += 1


# // Finding all 4 digit prime numbers
def SieveOfEratosthenes(v):
    # Create a boolean array "prime[0..n]" and initialize all entries it as true. A value in prime[i] will be
    # finally be false if i is Not a prime, else true.
    n = 9999
    prime = [True] * (n + 1)
    p = 2
    while p * p <= 9999:
        if prime[p]:
            i = p * p
            while i <= 9999:
                prime[i] = False
                i = i + p
        p = p + 1
    # v = []
    for i in range(1000, n + 1):
        if prime[i]:
            v.append(i)
    return v


def compare(a, b):
    diff = 0
    while a:
        if a % 10 != b % 10:
            diff += 1
        a //= 10
        b //= 10
    # If the numbers differ only by a single # digit return true else false
    if diff > 1:
        return False
    return True


def shortestPath(num1, num2):
    # Generate all 4 digit
    pset = []
    SieveOfEratosthenes(pset)
    # Create a graph where node numbers # are indexes in pset[] and there is
    # an edge between two nodes only if # they differ by single digit.
    g = Graph(len(pset))
    for i in range(len(pset)):
        for j in range(i + 1, len(pset)):
            if compare(pset[i], pset[j]):
                g.addedge(i, j)
    # Since graph nodes represent indexes # of numbers in pset[], we find indexes of num1 and num2.
    in1, in2 = None, None
    for j in range(len(pset)):
        if pset[j] == num1:
            in1 = j
    for j in range(len(pset)):
        if pset[j] == num2:
            in2 = j
    return g.bfs(in1, in2)


# Driver code
if __name__ == '__main__':
    num1 = 1033
    num2 = 8179
    print(shortestPath(num1, num2))