深搜1 —— Prime Ring Problem

Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, …, n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.

Note: the number of first circle should always be 1.
Input
n (0 < n < 20).

Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.

You are to write a program that completes above process.

Print a blank line after each case.

Sample Input
6
8

Sample Output
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

題意:給你數字n( 0 < n < 20),然後全排列,要求輸出的是相鄰的兩個數和是素數,坑點,第一個和最後一個相加也是素數, 而且第一個數必須是1。然後按照樣例那樣輸出。
以前做過這個題,但是。。又超時了,原因第一個數是1,所以,不用廣搜那麼多次,所以,優化是必然的。先看一下Time Limit Exceeded的代碼

#include <stdio.h>
#include <string.h>
int vis[1000], xx[1000];
int isprime(int x)
{
    if(x <= 1) return 0;
    else
    {
        for(int i = 2; i < x; i++)
        {
            if(!(x % i)) return 0;
        }
        return 1;
    }
}
void dfs(int deep, int x)
{
    if(deep == x)
    {
        if(xx[0] == 1 && isprime(xx[0] + xx[x - 1]))
        {
            int ant = 0;
            for(int i = 1; i < x; i++)  // 找符合題意的情況
            {
                if(isprime(xx[i] + xx[i - 1])) ant++;
            }
            if(ant == x - 1)
            {
                for(int i = 0; i < x; i++) //符合的情況輸出
                    printf(i ? " %d" : "%d", xx[i]);
                puts("");
                return ;
            }
        }
    }
    for(int i = 1; i <= x; i++)
    {
        if(!vis[i])
        {
            vis[i] = 1;                 //直接先把所有的情況存起來
            xx[deep] = i;
            dfs(deep + 1, x);
            vis[i] = 0;
        }
    }
}
int main()
{
    int n;
    int k = 1;
    while(~scanf("%d", &n))
    {
        printf("Case %d:\n", k++);
        memset(vis, 0, sizeof(vis));
        dfs(0, n); //注意
        puts("");
    }
    return 0;
}

超時的原因是n < 20, 20層for循環肯定爆,所以再看一下優化後的代碼

#include <stdio.h>
#include <string.h>
int vis[100], xx[100], n;
int is(int x)
{
    if(x <=  1) return 0;
    else
    {
        for(int i = 2; i < x; i++)
        {
            if(x % i == 0) return 0;
        }
        return 1;
    }
}
void dfs(int deep)
{
    int ant = 0;
    xx[0] = 1;
    if(deep == n)
    {
        if(is(xx[0] + xx[n - 1]))
        {
            for(int i = 0; i < n; i++)
                printf(i ? " %d" : "%d", xx[i]);
            puts("");
        }
    }
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i])
        {
            xx[deep] = i;
            if(is(xx[deep] + xx[deep - 1]))  // 直接找符合題意的,把1略掉
            {
                vis[i] = 1;
                dfs(deep + 1);
                vis[i] = 0;
            }
        }
    }
}
int main()
{
    int k = 1;
    while(~scanf("%d", &n))
    {
        printf("Case %d:\n", k++);
        memset(vis, 0, sizeof(vis));
        dfs(1);  //注意
        puts("");
    }
    return 0;
}

比較一下就知道有什麼不同了吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章