第一次写博客(其实是第二篇),请大佬们不要打我。以下内容纯手写,保证原创,如有部分雷同纯属巧合。
其实我很犹豫很害怕,我一个初学者写代码博客,怕极了被网络大佬们“追杀”,犹豫多时,我决定以一个初学者的视角写下这篇东西,如果有什么网络规则啊,错误啊,不好的地方请各位大佬大方指出,我一定改!
深度优先搜索dfs就是一条路走到底,不通就回头继续下一个尝试,直到所有可能都被尝试完就结束。
核心思想就是递归,回溯。
代码框架就是终止条件,标记点,下一步dfs递归调用,返回。dfs多次出现return语句。
题目传送门(个人喜欢蓝色怪我咯)
正文:我是初学者,希望用优快云见证我的人生,写的不好,请各位大佬大胆指出,但请言语不要过激,谢谢。我爱ACM。
这是一道DFS基础题,没什么难点,数据量也低,不容易超时,所以也不需要剪枝(我还没学剪枝 来自咸鱼的绝望)。
下面这个代码我自我感觉良好啊,哇,写了很久,测试多次,以为能一次AC吧,呵呵!妄想。是菜就是菜,还敢妄想AC。至于错在哪呢?不妨先自己查查bug。
代码WA+PE+TE,哈哈,错的有点尴尬。
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int n; //全局变量,因为dfs中会用到
int a[22]; //一般dfs数组都定义为全局变量,初值为0
bool book[22]; //标记数组,初始值为false,但最好还是在main里进行清零操作(即memset函数)
bool fun(int t) //判定素数函数
{
for(int i=2; i<t; i++)
if(t%i==0)
return false;
return true;
}
void dfs(int step)
{
if(step==n+1) //步数为n+1表示所有数都用上了,即终点,返回
{
if(fun(1+a[step-1])) //到达终点后要把最后一个数和1的和进行素数判定
{
for(int j=1; j<step; j++)
cout << a[j] << ' ';
cout << endl;
}
return;
}
for(int i=1; i<=n; i++)
{
if(book[i]) //标记过的数都跳过
continue;
if(fun(i+a[step-1])) //判别素数
{
book[i]=true; //标记为已用或已走
a[step]=i; //当前步的值
dfs(step+1); //进行下一步dfs,此处step不是点,是步数
book[i]=false; //一条路走不通就取消标记
}
}
return; //所有路都不通就返回
}
int main()
{
cin >> n;
memset(book,false,sizeof(book)); //标记数组清零函数,有些oj好像不需要,但写上总没坏处吧
book[1]=true; //标记一号点为已走
a[1]=1; //题目默认a[1]=1
dfs(2); //从第二步开始dfs,理由同上
return 0;
}
上面得代码讲道理是没错得,错就错在HDU有严格得格式要求(人称“坑”)。所以说你完全可以不再看我下面得完整代码,自己修改上面得格式即可得到AC答案
改用scanf和printf是因为我害怕超时,dfs的时间复杂度很容易超时,一般需要很强的剪枝语句(我还不会,我太菜了)!
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
int n; //全局变量,因为dfs中会用到
int a[22]; //一般dfs数组都定义为全局变量,初值为0
bool book[22]; //标记数组,初始值为false,但最好还是在main里进行清零操作(即memset函数)
bool fun(int t) //判定素数函数
{
for(int i=2; i<t; i++)
if(t%i==0)
return false;
return true;
}
void dfs(int step)
{
if(step==n+1) //步数为n+1表示所有数都用上了,即终点,返回
{
if(fun(1+a[step-1])) //到达终点后要把最后一个数和1的和进行素数判定
{
printf("%d",a[1]);
for(int j=2; j<step; j++)
printf(" %d",a[j]);
printf("\n");
}
return;
}
for(int i=1; i<=n; i++)
{
if(book[i]) //标记过的数都跳过
continue;
if(fun(i+a[step-1])) //判别素数
{
book[i]=true; //标记为已用或已走
a[step]=i; //当前步的值
dfs(step+1); //进行下一步dfs,此处step不是点,是步数
book[i]=false; //一条路走不通就取消标记
}
}
return; //所有路都不通就返回
}
int main()
{
int sum=1;
while(scanf("%d",&n)!=EOF)
{
printf("Case %d:\n",sum++);
memset(book,false,sizeof(book)); //标记数组清零函数,有些oj好像不需要,但写上总没坏处吧
book[1]=true; //标记一号点为已走
a[1]=1; //题目默认a[1]=1
dfs(2); //从第二步开始dfs,理由同上
printf("\n");
}
return 0;
}