杭电1016 Prime Ring Problem DFS深搜

来源:互联网 发布:amazon listing 优化 编辑:程序博客网 时间:2024/05/15 20:07

这道题给我最大的困惑就是一开始看不懂题目。。


再看看,说白了就是输入n,在1至n的自然序列里,找到符合相邻两数之和是素数,且第一个与最后一个数之和也是素数(因为是环嘛)的序列并且输出。

这样把题目一翻译,就觉得相当适合深搜。


深搜的基本框架还是相对好搭好想的。


函数类型 dfs(参数列表)

{

        判断边界条件的代码,return


        判断是不是正确解的代码,return


        做一系列相应操作。


       递归调用dfs。

}


那么,在本题,很容易想到首先我们需要一个res[]数组来存储答案,判断为正确解的时候就把答案输出就可以了,而且根据题意这个res[1]总是1(res[0]不管,方便一一对应)

要判断两数之和是不是素数,那dfs的参数至少要有两个,一个是之前一个数,一个是当前数。

再加一个flag参数,表明我现在是往res里放到第几个数了?如果我已经放到第n个数而且符合第n个数加第一个数为素数,那么就已经可以输出了。


基于这个思路代码如下。

#include <iostream>using namespace std;int prime[12]={2,3,5,7,11,13,17,19,23,29,31,37};//这是翻了别的博主博客学的tip,因为最多20个数,至多19+20=39.所以没有必要专门写段代码来判断,简单判断就好int res[21]={};                                   //可以放最多20个数int occupied[21]={};                              //一一对应看看1到n都用过了没有,已经用过放进res的是1,反之是0int n;bool isPrime(int num)                             //简单判断这个数是不是题目所给范围内的素数{for(int i=0;i<12;i++){if(num==prime[i])return true;}return false;}void printRes()                                   //输出答案,注意格式{for(int i=1;i<n;i++)cout<<res[i]<<" ";cout<<res[n]<<endl;}bool dfs(int pre,int cur,int flag)                {if(!isPrime(pre+cur))                     //边界条件:如果前一个数pre和现在的数current相加不是素数,直接return    return false;res[flag]=cur;                            //是素数,那么把cur放进对应的第flag个数里。并且表明这个数已经被用过了。
occupied[cur]=1;   
        //把当前cur当成下一个数的pre,尝试下一个数        for(int i=2;i<=n;i++){if(occupied[i]!=1){bool ans=dfs(cur,i,flag+1);if(ans)break;}}        //路走不通要还原        occupied[cur]=0;return false;}int main(){    int cnt=0;    while(cin>>n)    {        for(int i=1;i<=n;i++)            occupied[i]=0;        res[1]=1;        cnt++;        cout<<"Case "<<cnt<<":"<<endl;        for(int i=2;i<=n;i++)        //(1,2,2)(1,3,2)...(1,n,2)            dfs(1,i,2);        cout<<endl;    }} 



0 0
原创粉丝点击