蓝桥杯DFS&BFS专题(入门)

蓝桥杯DFS&BFS专题

DFS

介绍

DFS是深度优先搜索算法,是一种用于图形搜索的算法。它的基本思想是:从初始状态出发,沿着最先发现的路径前进,直到最后可以到达目标状态为止

具体步骤如下:

  • 从初始状态出发,沿着第一条路径向前搜索;
  • 如果未到达终止状态,则继续沿着这条路径继续搜索;
  • 如果已经到达终止状态,则回溯,沿着另一条路径继续搜索;

img

伪代码

void dfs()//参数用来表示状态  
{  
    if(到达终点状态){  
        ...//根据题意添加  
        return;  
    }  ]
        
    //可能剪枝
    if(特殊状态)//剪枝
        return ;
    
    //重复过程
    for(扩展方式){  
        //满足什么条件才能重复继续的操作
        if(扩展方式所达到状态合法)  
        {  
            修改操作;//根据题意来添加  
            //标记;  
            dfs(); 
            
            //回溯操作
            (还原标记);  
            //是否还原标记根据题意  
        }  
 
    }  
} 

例题

测试链接

排列数字

给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法,现在,请你按照字典序将所有的排列方法输出

输入格式
共一行,包含一个整数 n。

输出格式
按字典序输出所有排列方案,每个方案占一行。

数据范围 : 1 ≤ n ≤ 7

输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
AC代码
  • C/C++

    #include 
    using namespace std;
    const int N = 10;
    int n;
    int path[N];//保存数字组合
    bool st[N];//检测该数字有没有用过
    void dfs(int x){
    	if (x==n){
    		for (int i = 0; i < n; i++){
    			cout << path[i];
    		}
    		cout << endl;
    		return;
    	}
     
    	for (int i = 1; i <= n; i++){
    		if (!st[i]){
    			path[x] = i;
    			st[i] = true;
    			dfs(x + 1);
    			st[i] = false;
    		}
    	}
    }
    int main(){
    	cin >> n;
    	dfs(0);
    	return 0;
    }
    
  • JAVA

import java.io.BufferedInputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    public static int n;
    public static int [] vis = new int[10];
    public static LinkedList path = new LinkedList<>();
    public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
    public static PrintStream ps = new PrintStream(System.out);
    public static void main(String[] args) {
        n = sc.nextInt();
        dfs(0);
    }

    private static void dfs(int x) {
        if (x == n){
            for (Integer item : path) {
                ps.print(item + " ");
            }
            ps.println();
            return ;
        }

        for (int i = 1; i <= n; i++) {
            if (vis[i] == 0){
                vis[i] = 1;
                path.add(i);
                dfs(x + 1);

                vis[i] = 0;
                path.removeLast();
            }
        }
    }
}
  • 技巧

    //其实就是一个全排列,可以调用对应函数或者API
    #include
    #include
    using namespace std;
    int path[10];
    int main(){
    	
    	int n ;
    	cin >> n;
    	for(int i = 1 ; i <= n ; i++) path[i] = i;
    	do{
    		for(int i = 1 ; i <= n ; i++){
    			cout << path[i];
    		}
    		cout << endl;
    	}while(next_permutation(path + 1,path + n + 1));
    	return 0;
    }
    
15级台阶

小蓝要上一个楼梯,共 15 级台阶。

小蓝每步可以上 1 级台阶,也可以上 2 级、3 级或 4 级,再多就没办法一步走到了。

每级台阶上有一个数值,可能正也可能负。每次走到一级台阶上,小蓝的得分就加上这级台阶上的数值。台阶上的数值依 次为: 1, 2, 1, 1, 1, 1, 5, 5, 4, -1, -1, -2, -3, -1, -9。

小蓝希望不超过 6 步走到台阶顶端,请问他得分的最大值是多少?

注意,小蓝开始站在地面上,地面没有分值。他最终要走到台阶顶端,所以最终一定会走到数值为 -9 的那级台阶,所以 -9

一定会加到得分里面。

AC代码

答案: 5

  • C++
#include
#include
using namespace std;
int score[16] = {0,1,2,1,1,1,1,5,5,4,-1,-1,-2,-3,-1,-9};
int ans;
void dfs(int x,int step,int grade) // 当前在 x 级台阶,用了step步,得了grade分 
{
	if(x > 15 || step > 6) return ;
	
	if(x == 15) {
		ans = max(ans,grade);
		return ;
	}
	
	for(int i = 1 ; i <= 4 ; i++){
		dfs(x + i,step + 1,grade + score[x + i]);
	}
} 
int main(){
	
	dfs(0,0,0);
	cout << ans << endl;
	return 0;
}
  • JAVA
import java.io.BufferedInputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {

    public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
    public static PrintStream ps = new PrintStream(System.out);

    public static int [] score = new int[]{0,1,2,1,1,1,1,5,5,4,-1,-1,-2,-3,-1,-9};
    public static int ans;
    public static void main(String[] args) {
        dfs(0,0,0);
        ps.println(ans);
    }

    private static void dfs(int x,int step,int grade) {
        if (x == 15) {
            ans = Math.max(ans,grade);
            return ;
        }

        for (int i = 1; i <= 4; i++) {
            if (x + i <= 15 && step <= 5)  dfs(x + i,step + 1, grade + score[i + x]);
        }
    }
}
剪邮票

题目链接

如下图, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)

比如,下图中,粉红色所示部分就是合格的剪取。

蓝桥杯DFS&BFS专题(入门)_第1张图片

请你计算,一共有多少种不同的剪取方法

AC代码

技巧

选不重复的方法

  • 从12个数中任意挑选5个数,用一个哈希表维护一个选取的数的记录,每次选取的数字都存入哈希表中,如果哈希表中已经存在该数字,则重新选择。

  • 可以先将12个数排序,然后从第一个数开始,每次挑选下一个数字即可,保证不会重复。

  • JAVA

    错误做法

    import java.io.BufferedInputStream;
    import java.io.PrintStream;
    import java.util.LinkedList;
    import java.util.Scanner;
    
    public class Main {
    
        public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
        public static PrintStream ps = new PrintStream(System.out);
        public static LinkedList path = new LinkedList<>();
        public static int [] vis = new int[15];
        public static int ans;
        public static void main(String[] args) {
           dfs(0,0);
           ps.println(ans);
        }
    
        private static void dfs(int x,int num) {
            if (num == 5){
                if (Check()) ans++;
                return ;
            }
    
            for (int i = x + 1; i <= 12; i++) {
                if (vis[i] == 0){
                    vis[i] = 1;
                    path.add(i);
                    dfs(i,num + 1);
    
                    vis[i] = 0;
                    path.removeLast();
                }
            }
    
        }
    
        private static boolean Check() {
            for (Integer item : path) {
                boolean flag = false;
    
                for (Integer item2 : path) {
                    if (item == item2) continue;
                    int abs = Math.abs(item - item2);
                    if (abs == 1 || abs == 4){  //在举例,会发现bug
                        flag = true;
                        break;
                    }
                }
                if (!flag) return false;
            }
            return true;
        }
    }
    
  • 正解

import java.io.BufferedInputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {

    public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
    public static PrintStream ps = new PrintStream(System.out);
    public static LinkedList<Integer> path = new LinkedList<>();
    public static int [] vis = new int[15];
    public static int [] a = new int[] {1,2,3,4,6,7,8,9,11,12,13,14};
    public static int ans;
    public static void main(String[] args) {
       dfs(-1,0);
       ps.println(ans);
    }

    private static void dfs(int x,int num) {
        if (num == 5){
            if (Check()) ans++;
            return ;
        }

        for (int i = x + 1; i < 12; i++) {
            if (vis[i] == 0){
                vis[i] = 1;
                path.add(a[i]);
                dfs(i,num + 1);

                vis[i] = 0;
                path.removeLast();
            }
        }

    }

    private static boolean Check() {
        int sum = 0;
        for (Integer item : path) {
            int temp = 0;
            for (Integer item2 : path) {
                if (item == item2) continue;
                int abs = Math.abs(item - item2);
                if (abs == 1 || abs == 5){
                    temp ++ ;
                }
            }
            if (temp == 0) return false;
            sum += temp;
        }
        //难点判断
        if (sum <= 6) return false;
        return true;

    }
}
  • C++
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

int a[12] = {1,2,3,4,6,7,8,9,11,12,13,14};
int vis[15];
int ans;
vector path;

bool Check(){
    int sum = 0;
    for (int i = 0; i < path.size();i++){
        int temp = 0;
        for (int j = 0;j < path.size();j++){
            if (i == j) continue;
            int cal = abs(path[i] - path[j]);
            if (cal == 1 || cal == 5){
                temp++;
            }
        }
        if (temp == 0) return false;
        sum += temp;
    }
    if (sum <= 6) return false;
    return true;
}

void dfs(int x,int num){
    if (num == 5){
        if (Check()) ans++;
        return ;
    }
    for(int i = x + 1; i < 12; i++){
        if (vis[i] == 0){
            vis[i] = 1;
            path.push_back(a[i]);
            dfs(i,num + 1);
            
            vis[i] = 0;
            path.pop_back();
        }
    }
}

int main() {
	dfs(-1,0);
	cout << ans << endl;
}

BFS

介绍

BFS(广度优先搜索)是一种经典的搜索算法,它常用于搜索图中的最短路径,解决最小化问题,以及在多种场景下的搜索和遍历。

特点:

  • 广度优先搜索的思想,其中每一步都会沿着图的宽度搜索,而不是深度搜索。

  • 一般用队列来实现。

  • 一般用于求解最短路径问题,可以在求解过程中,每一步都能获得最短路径的值

伪代码
//BFS伪代码

//使用队列queue和访问标记数组visited
queue queue; 
bool visited[MAX_SIZE]; 

//初始化
for (int i = 0; i < MAX_SIZE; i++) 
    visited[i] = false; 

//从源结点s出发
visited[s] = true; 
queue.push(s); 

//当队列非空时循环
while (!queue.empty()) { 
    //取出队首结点u
    int u = queue.front(); 
    queue.pop(); 

    //最终条件
    if(...条件){
        //需要的结果
        return ;
    }
    //对u的每个邻接结点进行检查
    for (int v = 0; v < MAX_SIZE; v++) { 
        //如果v未被访问
        if (!visited[v]) { 
            //标记v已被访问
            visited[v] = true; 
            //将v加入
            q.push(v);
        }
    }
}
    
例题
长草

题目链接

小明有一块空地,他将这块空地划分为 nm 列的小块,每行和每列的长度都为 1,小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。

请告诉小明,k 个月后空地上哪些地方有草。

输入描述

输入的第一行包含两个整数

接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。

接下来包含一个整数 k。 其中,2≤n,m≤1000,1≤k≤1000。

输出描述

输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。

样例

输入

4 5
.g...
.....
..g..
.....
2

输出

gggg.
gggg.
ggggg
.ggg.
AC代码
  • JAVA

    import java.io.BufferedInputStream;
    import java.io.PrintStream;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    
    public class Main {
        public static final int [] dx = {1,-1,0,0};
        public static final int [] dy = {0,0,1,-1};
        public static int [][] vis = new int[1001][1001];
        public static void main(String[] args) {
            Scanner sc = new Scanner(new BufferedInputStream(System.in));
            PrintStream ps = new PrintStream(System.out);
            int n = sc.nextInt();
            int m = sc.nextInt();
    
            char[][] arr = new char[n][m];
    
            for (int i = 0; i < n; i++) {
                arr[i] = sc.next().toCharArray();
            }
            int k = sc.nextInt();
    
            Queue  q = new LinkedList<>();
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (arr[i][j] == 'g'){
                        q.add(new Node(i,j,0));
                        vis[i][j] = 1;
                    }
                }
            }
    
            while (q.size() > 0){
                Node node = q.poll();
    
                if (node.step >= k) continue ;
                for (int i = 0; i < 4; i++) {
                    int fx = dx[i] + node.x;
                    int fy = dy[i] + node.y;
    
                    if (fx < 0 || fx >= n || fy < 0 || fy >= m) continue;
                    if (vis[fx][fy] == 1) continue;
    
                    vis[fx][fy] = 1;
                    q.add(new Node(fx,fy, node.step + 1));
                }
            }
    
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (vis[i][j] == 1) ps.print("g");
                    else ps.print(".");
                }
                ps.println();
            }
    
        }
    
    }
    class Node {
        int x,y,step;
    
        public Node(int x, int y, int step) {
            this.x = x;
            this.y = y;
            this.step = step;
        }
    }
    
  • C++

    #include 
    #include 
    #include 
    #include 
    using namespace std;
    int vis[1001][1001];
    int dx[4] = {1,-1,0,0};
    int dy[4] = {0,0,1,-1};
    int n,m,k;
    char arr[1001][1001];
    struct Node{
        int x,y,step;
        Node(int x,int y,int step):x(x),y(y),step(step){};
    };
    int main(){
        cin>>n>>m;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin>>arr[i][j];
            }
        }
        cin>>k;
    
        queue q;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (arr[i][j] == 'g'){
                    q.push(Node(i,j,0));
                    vis[i][j] = 1;
                }
            }
        }
    
        while(q.size() > 0){
            Node node = q.front();
            q.pop();
            if (node.step >= k) continue;
    
            for (int i = 0; i < 4; i++) {
                int fx = dx[i] + node.x;
                int fy = dy[i] + node.y;
                if (fx < 0 || fx >= n || fy < 0 || fy >= m) continue;
                if (vis[fx][fy] == 1) continue;
    
                vis[fx][fy] = 1;
                q.push(Node(fx,fy,node.step + 1));
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (vis[i][j] == 1) cout<<"g";
                else cout<<".";
            }
            cout<
走迷宫

题目链接

一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。

给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)

只能在水平方向或垂直方向走,不能斜着

输入描述

​ 第一行是两个整数,R和C,代表迷宫的长和宽( 1≤ R,C ≤ 40)

​ 接下来是R行,每行C个字符,代表整个迷宫

​ 空地格子用‘.’表示,有障碍物的格子用‘#’表示

​ 迷宫左上角和右下角都是‘.’

输出描述

输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)

计算步数要包括起点和终点,无法到达终点时输出 0

样例

输入

5 5
..###
#....
#.#.#
#.#.#
#.#..

输出

9
AC代码
  • JAVA
import java.io.BufferedInputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {

    public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
    public static PrintStream ps = new PrintStream(System.out);

    public static char [][] graph = new char[41][41];
    public static int [][] vis = new int[41][41];

    public static int [] dx = {1,-1,0,0};
    public static int [] dy = {0,0,1,-1};
    public static int n,m;

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();

        for (int i = 0; i < n; i++) {
            graph[i] = sc.next().toCharArray();
        }

        bfs();
    }

    private static void bfs() {
        Queue  queue = new LinkedList<>();

        queue.add(new Node(0,0,1));

        while (!queue.isEmpty()){
            Node node = queue.poll();

            if (node.x == n - 1 && node.y == m - 1){
                ps.println(node.step);
                return ;
            }

            for (int i = 0; i < 4; i++) {
                int fx = dx[i] + node.x;
                int fy = dy[i] + node.y;

                if (fx >= n || fx < 0 || fy >= m || fy < 0) continue;
                if (vis[fx][fy] == 1 || graph[fx][fy] == '#') continue;

                vis[fx][fy] = 1;
                queue.add(new Node(fx,fy,node.step + 1));
            }

        }
        ps.println(0);
    }

}
class Node {
    int x,y,step;

    public Node(int x, int y, int step) {
        this.x = x;
        this.y = y;
        this.step = step;
    }
}
  • C++

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    struct Node{
        int x;
        int y;
        int step;
    };
    
    char graph[41][41];
    int vis[41][41];
    
    int n,m;
    int dx[4] = {1,-1,0,0};
    int dy[4] = {0,0,1,-1};
    
    void bfs(){
        queue q;
        Node start;
        start.x = 0;
        start.y = 0;
        start.step = 1;
        q.push(start);
    
        while(!q.empty()){
            Node node = q.front();
            q.pop();
    
            if(node.x == n - 1 && node.y == m - 1){
                cout << node.step << endl;
                return;
            }
    
            for(int i = 0; i < 4; i++){
                int fx = node.x + dx[i];
                int fy = node.y + dy[i];
    
                if(fx < 0 || fx >= n || fy < 0 || fy >= m) continue;
                if(vis[fx][fy] == 1 || graph[fx][fy] == '#') continue;
    
                vis[fx][fy] = 1;
                Node next;
                next.x = fx;
                next.y = fy;
                next.step = node.step + 1;
                q.push(next);
            }
        }
        cout << 0 << endl;
    }
    
    int main(){
        scanf("%d %d", &n, &m);
        for (int i = 0; i < n; i++)  scanf("%s",graph[i]);
        bfs();
        return 0;
    }
    
全球变暖

题目链接

你有一张某海域 N * N 像素的照片,. 表示海洋, # 表示陆地,如下所示:

.......
.##....
.##....
....##.
..####.
...###.
.......

其中 “上下左右” 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没

例如上图中的海域未来会变成如下样子:

.......
.......
.......
.......
....#..
.......
.......

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

输入格式

第一行包含一个整数 N (1 ≤ N ≤ 1000)。

以下 N 行 N 列代表一张海域照片。

照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。

输出格式

一个整数表示答案

样例

​ 输入

7 
.......
.##....
.##....
....##.
..####.
...###.
.......

输出

1
AC代码

存在一个问题,是海洋有可能将未被淹没的岛屿给分隔开,即可能增加岛屿数量

  • JAVA

    import java.io.BufferedInputStream;
    import java.io.PrintStream;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    
    public class Main {
    
        public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
        public static PrintStream ps = new PrintStream(System.out);
    
        public static char [][] graph = new char[1001][1001];
        public static int [][] vis = new int[1001][1001];
    
        public static int [] dx = {1,-1,0,0};
        public static int [] dy = {0,0,1,-1};
        public static int n;
    
        public static void main(String[] args) {
            n = sc.nextInt();
    
            for (int i = 0; i < n; i++) {
                graph[i] = sc.next().toCharArray();
            }
            int num = 0,ans = 0;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
    
                    if (graph[i][j] == '#' && vis[i][j] == 0){
                        num ++;
                        ans += bfs(i,j);
                    }
                }
            }
            ps.println(num - ans);
        }
    
        private static int bfs(int x, int y) {
            Queue  queue = new LinkedList<>();
    
            queue.add(new Node(x,y));
    
            boolean flag = false;
    
            while (queue.size() > 0){
                Node node = queue.poll();
    
                if (isOK(node.x,node.y)) flag = true;
    
                for (int i = 0; i < 4; i++) {
                    int fx = dx[i] + node.x;
                    int fy = dy[i] + node.y;
    
                    if (fx < 0 || fx >= n || fy < 0 || fy >= n) continue;
                    if (vis[fx][fy] == 1 || graph[fx][fy] == '.') continue;
    
                    vis[fx][fy] = 1;
                    queue.add(new Node(fx,fy));
                }
            }
            if (flag) return 1;
            return 0;
        }
    
        private static boolean isOK(int x, int y) {
            for (int i = 0; i < 4; i++) {
                int fx = dx[i] + x;
                int fy = dy[i] + y;
                if (fx < 0 || fx >= n || fy < 0 || fy >= n) return false;
                if (graph[fx][fy] == '.') return false;
            }
            return  true;
        }
    
    }
    class Node {
        int x,y;
    
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
  • C++

    #include 
    #include 
    using namespace std;
    
    char graph[1001][1001];
    int vis[1001][1001];
    int dx[4] = {1,-1,0,0};
    int dy[4] = {0,0,1,-1};
    int n;
    
    struct Node {
        int x,y;
        Node (int x,int y):x(x),y(y){}
    };
    
    bool isOK(int x, int y) {
        for (int i = 0; i < 4; i++) {
            int fx = x + dx[i];
            int fy = y + dy[i];
            if (fx < 0 || fx >= n || fy < 0 || fy >= n) return false;
            if (graph[fx][fy] == '.') return false;
        }
        return  true;
    }
    
    int bfs(int x, int y){
        queue  queue;
        queue.push(Node(x,y));
    
        bool flag = false;
    
        while (queue.size() > 0){
            Node node = queue.front();
            queue.pop();
    
            if (isOK(node.x,node.y)) flag = true;
    
            for (int i = 0; i < 4; i++) {
                int fx = node.x + dx[i];
                int fy = node.y + dy[i];
    
                if (fx < 0 || fx >= n || fy < 0 || fy >= n) continue;
                if (vis[fx][fy] == 1 || graph[fx][fy] == '.') continue;
    
                vis[fx][fy] = 1;
                queue.push(Node(fx,fy));
            }
        }
        if (flag) return 1;
        return 0;
    }
    
    
    int main(){
        scanf("%d",&n);
    
        for (int i = 0; i < n; i++) scanf("%s",graph[i]);
        int num = 0,ans = 0;
        
    	for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (graph[i][j] == '#' && vis[i][j] == 0){
                       num ++;
                       ans += bfs(i,j);
                }
            }
        }
        printf("%d\n",num - ans);
    	 
    	return 0;   
    }
    

综合

学霸的迷宫
类似题目迷宫
  • JAVA
import java.io.BufferedInputStream;
import java.io.PrintStream;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {

    public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
    public static PrintStream ps = new PrintStream(System.out);
    
    public static int n,m;
    public static int [] dx = {1,0,0,-1};
    public static int [] dy = {0,-1,1,0};
    public static char [] dir = {'D','L','R','U'};
    public static char[][] graph;
    public static int[][] vis;
    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();

        graph = new char[n][m];
        vis = new int[n][m];

        for (int i = 0; i < n; i++) {
            graph[i] = sc.next().toCharArray();
        }

        bfs(0,0);
    }

    private static void bfs(int x, int y) {
        Queue  q = new LinkedList<>();

        q.add(new Node(x,y,0,""));

        while (q.size() > 0) {
            Node node = q.poll();

            if (node.x == n - 1 && node.y == m - 1){
                ps.println(node.step);
                ps.println(node.path);
                return ;
            }

            for (int i = 0; i < 4; i++) {
                int fx = node.x + dx[i];
                int fy = node.y + dy[i];

                if (fx >= n || fx < 0 || fy >= m || fy < 0) continue;

                if(vis[fx][fy] == 1 || graph[fx][fy] == '1') continue;

                vis[fx][fy] = 1;

                q.add(new Node(fx,fy,node.step + 1, node.path + dir[i] ));
            }
        }
    }

}
class Node {
    int x,y,step;
    String path;

    public Node(int x, int y, int step, String path) {
        this.x = x;
        this.y = y;
        this.step = step;
        this.path = path;
    }
}
  • C++

    
    #include 
    #include 
    #include 
    using namespace std;
    
    const int MAXN = 1005;
    int n,m;
    int dx[4] = {1,0,0,-1};
    int dy[4] = {0,-1,1,0};
    char dir[4] = {'D','L','R','U'};
    char graph[MAXN][MAXN];
    int vis[MAXN][MAXN];
    
    struct Node{
        int x, y, step;
        string path;
    };
    
    void bfs(int x, int y){
        queue q;
        q.push({x,y,0,""});
    
        while(!q.empty()){
            Node node = q.front();
            q.pop();
    
            if(node.x == n-1 && node.y == m-1){
                cout << node.step << endl;
                cout << node.path << endl;
                return;
            }
    
            for(int i=0; i<4; i++){
                int fx = node.x + dx[i];
                int fy = node.y + dy[i];
    
                if( fx<0 || fx>=n || fy<0 || fy>=m ){
                    continue;
                }
    
                if( vis[fx][fy] || graph[fx][fy]=='1' ){
                    continue;
                }
    
                vis[fx][fy] = 1;
                q.push({fx,fy,node.step+1, node.path + dir[i]});
            }
        }
    }
    
    int main(){
        cin >> n >> m;
    
        for(int i=0; i> graph[i][j];
            }
        }
    
        bfs(0,0);
    
        return 0;
    }
    
数的划分

链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2JhI4Kkq-1678429113875)(C:\Users\qwe\AppData\Roaming\Typora\typora-user-images\image-20230303162415427.png)]

  • 纯纯的dfs暴力

      • JAVA

        import java.io.BufferedInputStream;
        import java.io.PrintStream;
        import java.util.*;
        
        public class Main {
        
            public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
            public static PrintStream ps = new PrintStream(System.out);
            
            public static int n,ans;
            public static HashMap<String, Boolean> hp = new HashMap<>();
            public static void main(String[] args) {
                n = sc.nextInt();
        
                for (int i = 2; i <= n; i++) {
                    LinkedList<Integer> arr = new LinkedList<>();
                    dfs(i,i,arr,0);
                    hp.clear();
                    arr.clear();
                }
                ps.println(ans + 1);
            }
        
            private static void dfs(int cnt, int res, LinkedList<Integer> arr, int sum) {
                if (res == 0){
                    if (sum > n) return ;
                    arr.sort((o1, o2) -> o1 - o2);
                    String s = "";
                    for (Integer item : arr) {
                        s = s + item + '-';
                    }
                    if (!hp.getOrDefault(s,false)) {
        //                ps.println(s);
                        hp.put(s,true);
        //                ps.print(cnt + " ");
                        ans++;
                    }
                    return ;
                }
        
                for (int i = 1; i <= n - sum; i++) {
                    arr.addLast(i);
                    dfs(cnt,res - 1,arr,sum + i);
        
                    arr.removeLast();
                }
            }
        }
        
  • 能骗多少骗多少

正解

  • 动态规划

转移方程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ee0wNpWH-1678429113879)(C:\Users\qwe\AppData\Roaming\Typora\typora-user-images\image-20230303162248911.png)]

dp[i][j]表示用1~i这些数构造出j这个数的方案数

含义为:对于每一个数i我们都可以选k次,要想构成j,则由前i-1个数构成j-k*i
边界为:dp[i][0] = 1,构成0的方案数为1,即都不选。

AC代码

  • C++
#include
using namespace std;
const int N = 110;

int dp[N][N], n, ans;

int main(){
	cin>>n;
	for(int i = 0;i <= n;i ++) dp[i][0] = 1;
	
	for(int i = 1;i <= n;i ++){
        for(int j = 1;j <= n;j ++){
        	for(int k = 0;k*i <= n && k*i <= j;k ++){ // 第j个i个数用k次
                	dp[i][j] += dp[i-1][j-k*i];
        	}
    	}
    }
	cout << dp[n][n] << endl;
	return 0;
}
  • Java

    import java.io.BufferedInputStream;
    import java.io.PrintStream;
    import java.util.*;
    
    public class Main {
    
        public static Scanner sc = new Scanner(new BufferedInputStream(System.in));
        public static PrintStream ps = new PrintStream(System.out);
        public static int n;
        
        public static void main(String[] args) {
            n = sc.nextInt();
            int[][] f = new int[n + 1][n + 1];
    		// 初始化
            for (int i = 0; i <= n; i++)  f[i][0] = 1;
    
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    for (int k = 0; i * k <= n && k * i <= j ; k++) {
                        f[i][j] += f[i - 1][j - k * i];
                    }
                }
            }
            ps.println(f[n][n]);
        }
    }
    

你可能感兴趣的:(蓝桥杯,算法,深度优先,数据结构)