竞赛算法--深入递归(中)(DFS、回溯、剪枝等)

竞赛算法–深入递归(上)(DFS、回溯、剪枝等)

竞赛算法–深入递归(下)(DFS、回溯、剪枝等)

2. 深度优先搜索DFS–Depth-First Search

dfs:一条路走到黑
bfs:所有路口看一遍

2.1 无死角搜索 I

  • 数独游戏
  • 部分和(挑战程序设计竞赛)
  • 水洼数目
2.1.1 数独游戏

题目描述:
竞赛算法--深入递归(中)(DFS、回溯、剪枝等)_第1张图片
题目分析及代码:

  • 伪代码分析
  dfs(table , x, y){
        // table为数组  , x,y为坐标
       if(x==9){
     
           print(table);
           System.exit(0);
       }
       if(table[x][y] == '0'){
     
           // 选1-9之间的合法数字填到 x,y这个位置
           for( i= 1 .... 9){
     
               boolean res = check(table , x,y,i); //检查数字是否合法
               if(res){
     
                   table[x][y] = i ; // 转移到下一个状态
                   // x + (y+1)/9  代表y达到最大索引8时,换行即 x+1
                   // (y + 1) % 9  代表y的索引,达到最大索引8时,换行后 从0开始
                   dfs(table , x + (y+1)/9(y+1)%9);
               }
           }
           table[x][y] = 0;  // 回溯
       }else{
     
           // 继续找下一个需要处理的位置
           dfs(table , x + (y+1)/9(y+1)%9 );
       }
   }

完整代码:

public class Main{
     
    public class Main(String [] args){
     
        Scanner in = new Scanner (System.in);
        int [][] table = new char[9][9];
        for(int i=0;i<9;i++){
     
            for(int j=0;j<9;j++){
     
                table[i][j] = in.nextInt();
            }
        }
        solve(table,0,0);
    }
    private static void solve(int[][] table , int x,int y){
     
        if(x==9){
     
            print(table);
            System.exit(0);
        }
        if(table[x][y] == 0){
      // 虚位以待
            for(int k = 1;k<10;k++){
     
                if(check(table,x,y,k)){
     
                    table[x][y] = k;
                    solve(table,  x + (y+1)/9(y+1)%9);
                }
            }
            table[x][y] = 0;  // 回溯;
        }else{
     
             solve(table,  x + (y+1)/9(y+1)%9);
        }
    }
    private static void print(int[][] table){
     
        for(int i=0;i<9;i++){
     
            for(int j=0;j<9;j++){
     
                System.out.print(table[i][j]);
            }
            System.out.println();
        }
    }
    private static boolean check(char[][] table,int i , int j ,int k){
     
        //检查同行同列
        for(int l = 0 ; l < 9 ; l++){
     
            if(table[i][l] == k )  return false;
            if(table[l][j] == k )  return false;
        }
        // 检查小九宫格
        for(int l = (i/3)*3 ; l < (i/3+1)*3 ; l++ ){
     
            for(int m = (j/3)*3 ; m<(j/3)*3; m++){
     
                if(table[l][m] == k)  return false;
            }
        }
        return true;
    }
}
2.1.2 部分和

题目描述:

  • 给定整数序列a1,a2,…,an , 判断是否可以从中选出若干数,使他们的和恰好为k
  • 1 <= n <= 20
  • -10^8 <= ai <= 10^8
  • -10^8 <= k <= 10^8
  • 样例:
  • 输入:
  • n = 4
  • a = { 1,2,4,7}
  • k =13
  • 输出:
  • Yes (13 = 2 + 4 + 7)

题目分析+题解代码:

  • 方法一:类似于求子串的问题
    用到深入递归1.2.2的非空子集问题-二进制解法
在这里插入代码片
  • 方法二: dfs
import java.util.*;
public class Main{
      
    static int kk = 0;
    public static void main(String args[]){
     
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int [] a = new int[n];
        for(int i=0;i<n;i++){
     
            a[i] = in.nextInt();
        }
        int k = in.nextInt(); 
        kk = k;
        dfs(a,k,0,new ArrayList<Integer>());
    }
    private static void dfs(int [] a , int k ,int cur,ArrayList<Integer> ints){
     
        if(k==0){
     
            System.out.println("Yes ("+kk+"=");
            int size = ints.size();
            for(int i=0;i<size;i++){
     
                System.out.print(ints.get(i)+(i==size-1?"":"+"));
            }
            System.out.println(")");
            System.exit(0);
        }
        if(k<0 || cur == a.length)  return;
        dfs(a,k,cur+1,ints);// 不要cur这个元素
        ints.add(a[cur]);
        int index = ints.size()-1;
        dfs(a,k-a[cur],cur+1,ints);
        ints.remove(index);   // 回溯
    }
}
2.1.2 水洼数目

题目描述:
竞赛算法--深入递归(中)(DFS、回溯、剪枝等)_第2张图片竞赛算法--深入递归(中)(DFS、回溯、剪枝等)_第3张图片

import java.util.Scanner;
public class Main{
       
    static int n=0,m=0;
    public static void main(String [] args){
     
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();
        char[][] a = new char[n][m];
        for(int i=0;i<n;i++){
     
            a[i] = in.nextLine().toCharArray();
        }
        int count = 0;
        for(int i=0;i<n;i++){
     
            for(int j=0;j<m;j++){
     
                if(a[i][j]=='w'){
     
                    dfs(a,i,j);  // 清除一个水洼
                    count++;
                }
            }
        }
        System.out.println(count);
    }
    private static void dfs(char[][] a , int i,int j){
     
        a[i][j] = '.';
        for(int k =-1;k<2;k++){
       // -1 , 0, 1
            for(int l =-1;l<2;l++){
       // -1 , 0, 1
                if(k==0 && l==0)  continue;
                if( i+k >=0 && i+k<=n-1 && j+l>=0 && j+l<=m-1){
     
                    if(a[i+k][j+l] == 'w'){
     
                        dfs(a,i+k,j+l);
                    }
                }
            }
        }
    }
}

你可能感兴趣的:(算法竞赛--模板+例题)