从零开始的暴搜复习生活—DFS(CODE[VS] 1116 四色问题 1294 全排列 1295 N皇后问题)

递归回溯法算法框架[一]
int Search(int k)
 {
 for (i=1;i<=算符种数;i++)
  if (满足条件)
     {
    保存结果
    if (到目的地) 输出解;
              else Search(k+1);
    恢复:保存结果之前的状态{回溯一步}
     }
 }
递归回溯法算法框架[二]
int Search(int k)
 {
   if  (到目的地) 输出解;
     else
    for (i=1;i<=算符种数;i++)
     if  (满足条件) 
     {
       保存结果;
            Search(k+1);
       恢复:保存结果之前的状态{回溯一步}
     }
 }

例题:
1.CODE[VS] 1294 全排列
题目描述 Description
给出一个n, 请输出n的所有全排列

输入描述 Input Description
读入仅一个整数n (1<=n<=10)

输出描述 Output Description
一共n!行,每行n个用空格隔开的数,表示n的一个全排列。并且按全排列的字典序输出。

样例输入 Sample Input
3

样例输出 Sample Output
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

#include<iostream>
#include<cstdio>
using namespace std;
int n,num[12];
bool pd[12];
void dfs(int x) 
{
    if (x == n)
    {
        for(int i = 1; i <= n; i ++)
        printf("%d ",num[i]);
        printf("\n"); 
        return;
    }
    for(int i = 1; i <= n ; i ++)
    {
        if(!pd[i])
        {
            pd[i] = 1;
            num[x + 1] = i;
            dfs(x + 1);
            pd[i] = 0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(0);
    return 0;
}

2.CODE[VS]1116 四色问题
题目描述 Description
给定N(小于等于8)个点的地图,以及地图上各点的相邻关系,请输出用4种颜色将地图涂色的所有方案数(要求相邻两点不能涂成相同的颜色)

数据中0代表不相邻,1代表相邻

输入描述 Input Description
第一行一个整数n,代表地图上有n个点

接下来n行,每行n个整数,每个整数是0或者1。第i行第j列的值代表了第i个点和第j个点之间是相邻的还是不相邻,相邻就是1,不相邻就是0.

我们保证a[i][j] = a[j][i] (a[i,j] = a[j,i])

输出描述 Output Description
染色的方案数

样例输入 Sample Input
8
0 0 0 1 0 0 1 0
0 0 0 0 0 1 0 1
0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
1 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0

样例输出 Sample Output
15552

数据范围及提示 Data Size & Hint
n<=8

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int map[10][10],n,clr[100],ans=0;
void dfs(int x)
{
    if(x > n)
    {
        ans ++;
        return;
    }
    for(int i = 1; i <= 4 ; i ++)//四种颜色 
    {
        bool key = 0;//判断相邻点的颜色 
        for(int j = 1;j <= n; j ++)
        {
            if(map[x][j] == 1 && i == clr[j])//如果当前点与j相邻且颜色相同 
            {
                key = 1;
                break;
            }
        }
        if(key) continue;
        if(!key)//回溯 在开始进行重新染色 
        {
            key = 1;
            clr[x] = i;
            dfs(x + 1);
            clr[x] = 0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n; i ++)
    for(int j = 1;j <= n; j ++)
        scanf("%d",&map[i][j]);
    dfs(1);
    cout << ans;
    return 0;   
}

3.CODE[VS]1295 N皇后问题
题目描述 Description
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。

输入描述 Input Description
给定棋盘的大小n (n ≤ 13)

输出描述 Output Description
输出整数表示有多少种放置方法。

样例输入 Sample Input
8

样例输出 Sample Output
92

数据范围及提示 Data Size & Hint
n<=13

本题显然每行只能有一个皇后 所以保证每个皇后不被攻击只需要判断每一列上即两条对角线上的情况即可

#include<iostream>
#include<cstdio>
using namespace std;
int n,ans = 0,num[15];
bool b[30] = {0}, c[30] = {0}, d[30] = {0};
//b 为列 c(横纵坐标纸和相同)从右上到左下 d(横纵坐标之差相同)是从左上到右下 
void dfs(int x)
{
    for(int i = 0;i < n; i ++)//逐行搜素 x为行 i为列 
    {
        if(!b[i] && !c[x + i] && !d[x - i + n - 1])//+n防止数组出现负数 
        {
            num[x] = i;
            b[i] = 1;
            c[x + i] = 1;
            d[x - i + n - 1] = 1;
            if(x == n)
            {
                ans ++; 
            }
            else    
            dfs(x + 1);
            b[i] = 0;
            c[x + i] = 0;
            d[x - i + n - 1] = 0;
        }
    }
    return;
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值