第八章:深度优先搜索进阶

深度优先搜索应用例题1:字母排列(主题库2698)给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。我们假设对于小写字母有 'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。输入格式  输入有多组数据,每行一组,每组数据是一个由小写字母组成的字符串,已知字符串的长度在 1 到 6 之间。输出格式  输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字典序如下定.
摘要由CSDN通过智能技术生成

 深度优先搜索应用

例题1:字母排列(主题库2698)

给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有 'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。

输入格式

  输入有多组数据,每行一组,每组数据是一个由小写字母组成的字符串,已知字符串的长度在 1 到 6 之间。

输出格式

  输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字典序如下定义:
  已知 S = s_1s_2...s_k , T = t_1t_2...t_kS=s1​s2​...sk​,T=t1​t2​...tk​,则 S < TS<T 等价于,存在 p (1 <= p <= k)p(1<=p<=k),使得 s_1 = t_1, s_2 = t_2, ..., s_{p - 1} = t_{p - 1}, s_p < t_ps1​=t1​,s2​=t2​,...,sp−1​=tp−1​,sp​<tp​ 成立。
  注意每组样例输出结束后接一个空行。

样例输入

xyz

Copy

样例输出

xyz
xzy
yxz
yzx
zxy
zyx

Copy

解题思路:详细解题思路见代码解析。

#include<bits/stdc++.h>
using namespace std;
char a[10];
int n,use[10];
string s; 
void print()
{
    for(int i=1;i<=n;i++)  
    {
        cout<<a[i];
    }
    cout<<endl;
}
void dfs(int cur)  //当前位置 
{
    if(cur>n)   //当前位置大于n,结束 
    {
        print();  //输出该种排列 
        return;
    }
    for(int i=0;i<=n-1;i++)  //枚举第cur个元素的值
    {
        if(use[i]==0)  //i没有被前面的元素使用
        {
            a[cur]=s[i];  //记录元素值
            use[i]=1;   //标记i被使用
            dfs(cur+1);  //搜索下一个元素的值
            use[i]=0;   //使用完,恢复状态
        }
    }
}
int main()
{
    while(cin>>s)
    {
        n=s.size();
        dfs(1);    //从第一个位置开始排
        cout<<endl;
    }
     return 0;
}

Copy

例题2:N皇后问题(主题库1285)

要在国际象棋棋盘中放n个皇后(棋盘大小为n*n),使任意两个皇后都不能互相吃。(提示:皇后能吃同一行、同一列、同一对角线的任意棋子。)

输入格式:输入一行,包含一个正整数n(n <= 8)。

输出格式:如果存在符合条件的放置方法,输出所有解,每组解占一行,其中每个数字占 5 个字符宽度,右对齐;如果不存在符合条件的解,则输出“no solute!”(不包含引号)。

样例输入:

4

Copy

样例输出:

2   4   1   3
3   1   4   2

Copy

样例解释:

如下图所示,当n=4时,皇后放置的两种解法:

解法1:第一行的2列,第二行的4列,第三行的1列,第四行的3列。组成一起就是2 4 1 3

解法2:第一行的3列,第二行的1列,第三行的4列,第四行的1列。组成一起就是3 1 3 2

解题思路:详细解题思路见代码解析。

#include<bits/stdc++.h>
using namespace std; 
int a[10];  //记录第i行的皇后放在第几列 
int n,ans=0;
bool check(int row,int col){ //判断第row行的皇后摆在第col列行不行 
    for(int i=1;i<row;i++)  //i表示行号,a[i]表示列号 
    {
        if(a[i]==col||(abs(row-i)==abs(col-a[i])))  //如果列号已经存在或者在斜对角线上,行的变化值等于列的变化值 
        return false;
    }
    return true; 
} 
void dfs(int cur)
{
    if(cur>n){ //从上往下摆,摆到第n+1行结束,即到达目的地 
        ans++;  //摆法++ 
        for(int i=1;i<=n;i++)  //具体摆法 
        {
            cout<<setw(5)<<a[i];  //i表示行号,a[i]表示列号,输出列号,即具体摆法 
        }
        cout<<endl;
        return; //void类型函数,return不加返回值表示函数结束 
    } 
    for(int i=1;i<=n;i++) //如果没有到第n+1行,就需要从一列摆到第n列,同时要判断该列能不能摆 
    {
        if(check(cur,i)==true)  //cur代表行,i代表列,表示该位置可以摆 
        {
            a[cur]=i;  //第cur行的皇后放在第i列
            dfs(cur+1);  //开始搜索下一行 
        } 
    }
}
int main()
{
    cin>>n;
    dfs(1); //从第一行开始
    if(ans==0) 
    cout<<"no solute!";
    return 0; 
}

Copy

例题3:八皇后问题

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 × 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。

对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。

已经知道8皇后问题一共有92组解(即92个不同的皇后串)。

给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入格式:第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1≤b≤92)。

输出格式:输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

输入样例1:

2
1
92

Copy

输出样例1:

15863724
84136275

Copy

解题思路:详细解题思路见代码解析。

#include<bits/stdc++.h>using namespace std;int res[100];   //存放每种摆法 int n,t=0,a[100];bool check(int x,int y)  //检查是否可以摆 {   for(int i=1;i<x;i++)    {       if(a[i]==y||abs(x-i)==abs(a[i]-y))  //横竖以及斜线            return false;   }   return true;}int make()  //将1 5 8 6 3 7 2 4合成15863724 { int x=0;    for(int i=1;i<=8;i++)   {       x=x*10+a[i];    }   return x;}void dfs(int cur) {   if(cur>8)  //不要写成n了,这里是8皇后,如果超过8,记录     {       t++;        res[t]=make();  //res[1]存放第一种摆法,以此类推...         return ;            }   for(int i=1;i<=8;i++)  //8行 {       if(check(cur,i)==true)  //是否可以摆         {           a[cur]=i;  //记录元素值          dfs(cur+1);  //搜索下一个元素的值        }   }}int main(){   int q,m;    dfs(1); cin>>q; //sort(res+1,res+1+92);  //可以不用排序,本来已经排好序了  for(int i=1;i<=q;i++)   {       cin>>m;     cout<<res[m]<<endl;  //res[m]即为所求   }}

Copy

例题4:小李去放牛

终于,小李在他 60 岁的时候下定决心,离开了城市,来到了农村生活,过起了田园生活.....(小李长成了老李了)

农村的生活非常闲适,小李还养了一头老黄牛,并且经常牵着这头老黄牛去牧场上吃草。这头牛有一个独特的能力——在牧场中能像中国象棋中的马一样跑跳。当然,这头牛不能跳到岩石或树上,不 过能跳到有牧草的地方。

这儿有一个宽为 X&#

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值