搜索专题(DFS)HDU 1016-Prime Ring Problem

来源:互联网 发布:浙江诸暨淘宝司法拍卖 编辑:程序博客网 时间:2024/05/18 07:07

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1016

思路分析:

首先看到数据范围不超过20,那就把40以内的素数打表存在数组里吧,然后确定搜索方式,一开始想的是BFS,结果发现很难写,主要是很难标记哪些数用过,哪些数没用过,不可能给每一种情况单独开一个数组,因为那样的话至少需要20!(2*10^18)个数组。改用DFS,还有一个问题是求出的数组怎么储存并打印出来。我用的是list,在进入下一层递归前把数插入到尾部,并且给它在标记数组中做上标记,出来时把尾部数删除并把标记去除。后来看了下别人写的代码,其实只用一个数组来存就可以了,新的递归函数会原先的数覆盖。这道题多次想看题解,不过还是忍住没看放了两天自己做出来了,这样应该比直接看题解要好得多,以后碰到不会的题先放放。

另外吐槽下这道题的格式控制,我明明是按照输出格式来的却死活通不过,它每个Case结束后要输出两个空行(最后一个数组会输出一个,case结束又输出一个)。样例里面是只有一个而且最后一个case是不输出空行的。

代码实现:

#include"cstdio"#include"list"using namespace std;bool su[40]={0};int n,first=1;int mark[22]={0,1};list<int> lis;//用来存放结果,可以把它换成普通数组,每次尾插时根据cnt来控制位置void DFS(int cnt,int x){    if(cnt==n)    {        if(su[x+1])        {            list<int>::iterator it;            for(it=lis.begin();it!=lis.end();it++)            {                if(it==lis.begin())                    printf("%d",*it);                else                printf(" %d",*it);            }            printf("\n");        }    }    for(int i=2;i<=n;i++)    {        if(!mark[i]&&su[x+i])        {            mark[i]=1;//进入下一层前把i标记            lis.push_back(i);//插入到链表尾部            DFS(cnt+1,i);            mark[i]=0;//第cnt个数字是i的已经检索完毕,清除标记            lis.pop_back();//删除链表尾部数字        }    }}int main(){    //40以内素数集合,直接打表    su[2]=su[3]=su[5]=su[7]=su[11]=su[13]=su[17]=su[19]=su[23]=su[29]=su[31]=su[37]=1;    int i=1;    while(~scanf("%d",&n))    {        first=1;        lis.clear();//清空        printf("Case %d:\n",i++);        lis.push_back(1);        DFS(1,1);        printf("\n");    }    return 0;}


0 0
原创粉丝点击