• DFS · 素数环(HDU_1016)


    DFS简析:

    DFS(深度优先搜索) ,搜索方法是从起点开始,从某一方向一层一层往下找,直到最底层,

    进行操作之后然后返回上一层换一个方向继续寻找,寻找方法有点类似根树遍历方法的前序遍历,一支一支找完之后,就完成了遍历

    搜索。

    实现这个算法很简单,其“本体”就是一个递归函数,如果某一方向的子支还不是最底层且满足题给条件,那么就继续调用它本身,

    直到不满足递归条件(及达到最底层或不满足继续循环的条件),那么操作后进行返回,让其开始下一个方向的寻找。

    不得不提到的是剪枝,DFS算法很容易超时,所以剪枝问题就是重中之重,不仅有题上所给的限定条件,一般还会有一系列的隐形条件,

    但剪枝方法因题而异,此处也不方便细说。

    下面看例题:(HDU_1016)

    素数环问题,即给定一个数n,能不能将从1开始到n(n<=20)结束的n个数排列呈环状,并且使相邻的两个数之和为素数

    输入有很多样例,每一个样例一个数n,且输入以0结尾,

    对于每一个数n,首先输出"Case x:",x为当前样例个数,若存在这样的环,则从1开始依次输出,若不存在则输出"no answer"

    且每一个样例后都要输出一个空行。

    怎么解决这个问题呢?

    我首先用埃氏筛法得到一个长为四十的数表,若下标数为素数,则存入1,否则存入0,

    其次用DFS搜索,如果能将这n个数全部按要求排列起来,那么就输出这个排列,

    而其间有一个小小的剪枝,若输入一个奇数,且排成环,那么这个环中肯定会有两个奇数相邻,

    而这两个奇数不可能都为1,所以他们的和一定为合数,所以直接输出"no answer"就好了

    代码:

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    int a[25];//存放排好的数
    int b[40];//判断下标是否为素数的数表
    int visited[25];//记录点是否被走过
    int n;
    int flag = 0;//记录是否存在素数环
    void dfs( int m, int ans )
    {
        a[ans] = m;
        visited[m] = 1;
        if( ans == n-1 )
        {
            if( b[m+1] )
            {
                for( int i(0); i < n; i++ )
                {
                    if( i == 0 )
                    {cout << a[i];continue;}
                    cout << " " << a[i];
                }
                cout << endl;
                flag++;
            }
        }
        else
        {
            for( int i = 1; i <= n; i++ )
            {
                if( b[i+m] && !visited[i] )
                    dfs( i, ans+1 );
            }
        }
        visited[m] = 0;
    }
    main()
    {
        int t = 0;
        memset( b, 1 ,sizeof(b) );//埃氏筛法
        b[0] = 0; b[1] = 0;
        for( int i(0); i*i <= 40; i++ )
            if ( b[i] )
                for( int j = 2*i; j <= 40; j += i )
                    b[j] = 0;
        while( cin >> n )//输入
        {
            if( !n )
                break;
            if( n%2 == 1 )//剪枝
            {
                cout << "Case " << ++t << ":
    ";
                cout << "no answer" << endl << endl;
            }
            memset( a, 0, sizeof(a) );
            memset( visited, 0, sizeof(visited) );
            cout << "Case " << ++t << ":
    ";
            dfs( 1, 0 );
            cout << endl;
            if( !flag )//若flag仍为0,说明名优任何的环形成,所以no answer
            {
                cout << "Case " << ++t << ":
    ";
                cout << "no answer" << endl << endl;
            }
        }
    }
  • 相关阅读:
    MVC3 验证码
    说说.NET反编译工具
    HTTP协议学习
    Spring Web Flow 的优缺点
    Java CLASSPATH 引发的问题
    MySQL 高级
    Java Policy
    AJAX
    数据结构与算法学习资源
    C#学习资源
  • 原文地址:https://www.cnblogs.com/xujunming/p/6715532.html
Copyright © 2020-2023  润新知