DFS专练

来源:互联网 发布:深圳软件基地 编辑:程序博客网 时间:2024/04/28 16:14

一、N皇后问题

问题描述:

在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n的棋盘上放置n个皇后,任何2个皇后不能在同一行或同一列或同一斜线上。


思路:

要解决N皇后问题,其实就是要解决好怎么放置这n个皇后,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线,我们可以以行优先,就是说皇后的行号按顺序递增,只考虑第i个皇后放置在第i行的哪一列,所以在放置第i个皇后的时候,可以从第1列判断起,如果可以放置在第1个位置,则跳到下一行放置下一个皇后。如果不能,则跳到下一列...直到最后一列,如果最后一列也不能放置,则说明此时放置方法出错,则回到上一个皇后向之前放置的下一列重新放置。此即是回溯法的精髓所在。当第n个皇后放置成功后,即得到一个可行解,此时再回到上一个皇后重新放置寻找下一个可行解...如此后,即可找出一个n皇后问题的所有可行解。

代码:

#include<stdio.h>#include<math.h>int n;int sum=0;int a[20];   //表示放置皇后的列数int check(int k){    int i;    for(i=0;i<k;i++)    //判断是否和前边几行放置的皇后产生冲突        if ( a[k]==a[i] || fabs(k-i)==fabs(a[k]-a[i]))// 列是否冲突 || 对角线是否冲突            return 0;        return 1;}void dfs(int row){    int i;    if(row==n)        sum++;    else    {        for(i=0;i<n;i++)        {            a[row]=i;   //表示第row个皇后放在第row行第i列            if(check(row))   // 判断第row行皇后能否放置                dfs(row+1);   //如果能放置,再判断下一行        }    }}int main (){    scanf("%d",&n);    dfs(0);  //从第一行开始搜索    printf("%d\n",sum);    return 0;}
二、素数环问题(HDU 1016)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1016

问题描述:

给定一个数n,有1到n共n个自然数,使这n个自然数组成一个环,要求环中相邻两个数之和为素数,求能够组成这种环的所有情况。

比如n=8,满足条件的素数环有:

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

共4种可能。


思路:

对每一个位置的数进行循环遍历,每次都把1到n搜索一遍,符合条件就填进去(记录下来),扫描下一个位置的数字,不符合条件的就跳过。


代码:

#include <stdio.h>#include <string.h>int flag[30];    //标记已经选过的数,1为选,0为未选。int a[100];      //存放自然数int n;int check(int x)   //判断是否为素数{    int i;    for(i=2;i<x;i++)        if(x%i==0)            return 0;    return 1;}void DFS(int k,int index){   int i;   a[k]=index;flag[index]=1;       //一开始先默认选index放在第k个位置,并将flag置1;   if(k==n)   {     if(check(a[k]+a[1]))    //判断第一个和最后一个是否满足条件     {        printf("1");       for(i=2;i<=n;i++)       //如果满足说明搜索结束,输出结果        printf(" %d",a[i]);       printf("\n");     }     return ;   }   for(i=1;i<=n;i++)        //每回从第一个开始搜索   {       if(!flag[i]&&check(a[k]+i))       {           DFS(k+1,i);          flag[i]=0;        //注意回溯       }   }  return ;}int main(){    int t=1;    while(scanf("%d",&n)!=EOF)    {      printf("Case %d:\n",t++);      memset(flag,0,sizeof(flag));    //标志位数组清0;      DFS(1,1);      printf("\n");    }    return 0;}



1 0
原创粉丝点击