dfs专题

58 篇文章 1 订阅

dfs专栏

本质上是暴力把所有的路径都搜索出来,它运用了回溯,保存这次的位置并深入搜索,都搜索完便回溯回来,搜下一个位置,直到把所有最深位置都搜一遍(找到目的解返回或者全部遍历完返回一个事先定好的值)。要注意的一点是,搜索的时候有记录走过的位置,标记完后可能要改回来。
dfs一般借用递归完成整个算法的构造。
img

1、Description
Michael喜欢滑雪这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道在一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
Sample Input
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output
25

int R, C;
int map[101][101];
int dp[101][101] = {1};
int dxy[4][2] = {
        {0,1},
        {1,0},
        {0, -1},
        {-1, 0}
};

int k = 1;

int dfs(int x, int y){
    if (dp[x][y]) return dp[x][y];
    for(int i = 0; i < 4; i++){
        int dx = x+dxy[i][0];
        int dy = y+dxy[i][1];
        if(dx>=0&&dx<R&&dy>=0&&dy<C&&map[dx][dy]<map[x][y]){
            k = dfs(dx,dy)+1;
            dp[x][y] = k>dp[x][y]? k: dp[x][y];
        }
    }
    return dp[x][y];

}
int main(){
    cin>>R>>C;
    int max = 0;
    for(int i = 0; i < R; i ++){
        for(int j = 0; j < C;j ++){
            cin>>map[i][j];
        }
    }
    for(int i = 0; i < R; i ++){
        for(int j = 0; j < C;j ++){
            int temp = dfs(i, j);
            max = max>temp?max: temp;
        }
    }
    cout<<max;
    return 0;
}

这个题就是把每个数从四个方向都遍历一次,如果满足递减的话就接着dfs,不满足时候把这个数存起来
这个题有几个注意的问题,就是第一个要考虑好边缘临界点,就是四周的点不可以进行某些方向的移动,其次还有一点特别要注意,dfs中的if (mark[i][j]) return mark[i][j];这句话就是为了重复计算,假如从24开始的话已经算出来23,然后如果从25开始,遇到24的话直接可以找到23,而不用在遍历一次,节省了时间。

2、八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

Input

无输入。
Output

按给定顺序和格式输出所有八皇后问题的解(见Sample Output)。
Sample Input

Sample Output

No. 1
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
No. 2
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 1 0 0 0 0 0 
No. 3
1 0 0 0 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 1 0 0 0 0 
0 1 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
No. 4
1 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
No. 5
0 0 0 0 0 1 0 0 
1 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 1 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 1 0 0 0 0 
No. 6
0 0 0 1 0 0 0 0 
1 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 1 0 0 
No. 7
0 0 0 0 1 0 0 0 
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 1 0 0 0 0 
0 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 1 0 0 
No. 8
0 0 1 0 0 0 0 0 
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
No. 9
0 0 0 0 1 0 0 0 
1 0 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 1 0 0 0 0 0 
...以下省略
————————————————

做这个题之前可以先就用8个for循环写一写,然后你就会清楚整个判断的流程是什么样的,然后再思考更像样得解法,注意写函数拆分各种功能。

#include <iostream>
using namespace std;

int map[10][10] = {0};//棋盘
int n = 8;
int queen_col[9];//每一行中皇后所在的列号
int count = 1;//统计第几种解法
void print(){
    for(int i = 0; i< 8; i++){
        map[i][queen_col[i]] = 1;
    }
    cout<<"方法"<<count++<<endl;
    for(int i = 0; i< 8; i++){
        for(int j = 0; j < 8; j++){
            cout<<map[i][j]<<" ";
        }
        cout<<endl;
    }
}
//判断当前行的皇后列号是否和上面的皇后同列或同斜线
bool judge(int row){
    for(int i = 0; i< row; i++){
        if(queen_col[i]==queen_col[row]||abs(queen_col[i]-queen_col[row]) == row-i)
            return false;
    }
    return true;
}



void dfs(int row){
    if(row ==8){//八行都判断完就打印
        print();
    }
    for(int i = 0; i < 8; i++){
        queen_col[row] = i;//当前行的皇后在第i列
        if(judge(row)){
            map[row][i] = 1;
            dfs(row+1);
            map[row][i] = 0;

        }
    }
}

int main(){
    dfs(0);//从第一行开始判断
    return 0 ;
}
 

答案:92种

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值