递归与递推

递归 

92. 递归实现指数型枚举 - AcWing题库

import java.util.*;

public class Main{
    static int N = 16, n;
    static int[] st = new int[N];//st[x] 等于0表示还没考虑到它,等于1表示选它,等于2表示不选它
    
    public static void dfs(int u){
        if(u > n){
            for(int i = 1; i <= n; i ++){
                if(st[i] == 1) System.out.print(i + " ");
            }
            System.out.println();
            return;//一定要记得返回return
        }
        
        //不选的情况
        st[u] = 2;
        dfs(u + 1);
        st[u] = 0;//恢复现场
        
        //选的情况
        st[u] = 1;
        dfs(u + 1);
        st[u] = 0;//恢复现场
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        dfs(1);//由于数字范围是1到n,所以这里的dfs要从1开始,不从0开始
    }
}

94. 递归实现排列型枚举 - AcWing题库

import java.util.*;

public class Main{
    static int N = 10, n;
    static int[] path = new int[N];//记录每一层的数
    static boolean[] st = new boolean[N];//用来判断这个数是否用过
    
    public static void dfs(int u){
        if(u > n){
            for(int i = 1; i <= n; i ++){
                System.out.print(path[i] + " ");
            }
            System.out.println();
        }
        
        for(int i = 1; i <= n; i ++){
            if(!st[i]){
                path[u] = i;
                st[i] = true;
                //递归下一层
                dfs(u + 1);
                //恢复现场
                path[u] = 0;
                st[i] = false;
            }
        }
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        dfs(1);
    }
}

93. 递归实现组合型枚举 - AcWing题库

限制:从小到大排序(局部限制),保证每次加的数都比前一个数大

import java.util.*;

public class Main{
    static int N = 30, n, m;
    static int[] state = new int[N];
    
    public static void dfs(int u, int start){
        if(u - 1 + n - start + 1 < m) return;//剪枝
        if(u == m + 1){
            for(int i = 1; i <= m; i ++){
                System.out.print(state[i] + " ");
            }
            System.out.println();
        }
        
        for(int i = start; i <= n; i ++){
            state[u] = i;
            dfs(u + 1, i + 1);
            state[u] = 0;//恢复现场
        }
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        
        dfs(1, 1);//从第一个位置开始,当前可以从1开始选
    }
}

1209. 带分数 - AcWing题库

import java.util.*;
import java.io.*;

public class Main{
    static int N = 20;
    static int n, res;
    static boolean[] st = new boolean[N], cpy = new boolean[N];
    
    public static void dfs_a(int u, int a){
        if(a >= n) return;//大于n直接返回
        
        if(a > 0) dfs_c(u, a, 0);//枚举c的所有排列方案
        
        for(int i = 1; i <= 9; i ++){
            if(!st[i]){
                st[i] = true;
                dfs_a(u + 1, a * 10 + i);
                st[i] = false;//恢复现场
            }
        }
    }
    
    public static void dfs_c(int u, int a, int c){
        if(u > 9) return;
        
        if(check(a, c)) res ++;
        
        for(int i = 1; i <= 9; i ++){
            if(!st[i]){
                st[i] = true;
                dfs_c(u + 1, a, c * 10 + i);
                st[i] = false;//恢复现场
            }
        }
    }
    
    public static boolean check(int a, int c){
        long b = (long) (n - a) * c;
        
        cpy = Arrays.copyOf(st, N);
        
        while(b > 0){
            int t = (int)(b % 10);
            b = b / 10;
            
            if(t == 0 || cpy[t]) return false;//如果t为0,或者被用过
            
            cpy[t] = true;
        }
        
        //检查是否有遗漏
        for(int i = 1; i <= 9; i ++){
            if(!cpy[i]) return false;
        }
        
        return true;
    }
    
    public static void main(String[] args)throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        
        dfs_a(0, 0);//一开始a和c共用0个数,a为0
        
        System.out.print(res);
    }
}

递推

717. 简单斐波那契 - AcWing题库

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int[] f = new int[46];
        f[1] = 0;
        f[2] = 1;
        
        int n = sc.nextInt();
        for(int i = 3; i <= n; i ++){
            f[i] = f[i - 1] + f[i - 2];
        }
        
        for(int i = 1; i <= n; i ++){
            System.out.print(f[i] + " ");
        }
    }
}
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int a = 0, b = 1;
        for(int i = 1; i <= n; i ++){
            System.out.print(a + " ");
            int c = a + b;
            a = b;
            b = c;
        }
    }
}

95. 费解的开关 - AcWing题库

        1.顺序可以任意

        2.每个格子最多按一次

        每一行开关的操作都被前一行的开关状态所决定 

import java.util.*;

public class Main{
    static int N = 6;
    static int[][] g = new int[N][N];
    static int[][] backup = new int[N][N];
    static int[] dx = {-1, 0, 1, 0, 0}, dy = {0, 1, 0, -1, 0};
    
    public static void turn(int x, int y){
        for(int i = 0; i < 5; i ++){
            int a = x + dx[i];
            int b = y + dy[i];
            if(a < 0 || b < 0 || a >= 5 || b >= 5) continue;
            g[a][b] ^= 1;
        }
    }
    
    public static int dfs(){
        int ans = 0x3f3f3f3f;
        
        //备份数组,用于多组测试(32)
        for(int i = 0; i < 5; i ++){
            for(int j = 0; j < 5; j ++){
                backup[i][j] = g[i][j];
            }
        }
        
        for(int k = 0; k < 1 << 5; k ++){
            int res = 0;//本次循环的结果
            
            //第一行
            for(int j = 0; j < 5; j ++){
                if((k >> j & 1) == 0){
                    res ++;
                    turn(0, j);
                }
            }
            
            for(int i = 0; i < 4; i ++){//第一行到第四行
                for(int j = 0; j < 5; j ++){//第一个数到第五个数
                    if(g[i][j] == 0){
                        res ++;
                        turn(i + 1, j);
                    }
                }
            }
            
            boolean flag = true;
            for(int j = 0; j < 5; j ++){//判断最后一行是否全为1
                if(g[4][j] == 0){
                    flag = false;
                    break;
                }
            }
            
            if(flag) ans = Math.min(ans, res);
            for(int i = 0; i < 5; i ++){
                for(int j = 0; j < 5; j ++){
                    g[i][j] = backup[i][j];//复原数组,便于下次循环
                }
            }
        }
        if(ans > 6) return -1;
        else return ans;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while(T -- > 0){
            for(int i = 0; i < 5; i ++){
                String s = sc.next();
                for(int j = 0; j < 5; j ++){
                    g[i][j] = s.charAt(j) - '0';//转化为int类型
                }
            }
            System.out.println(dfs());
        }
    }
}

1208. 翻硬币 - AcWing题库

次数和顺序没有关系 

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String a = sc.next();
        String b = sc.next();
        int res = 0;
        char[] A = a.toCharArray();
        char[] B = b.toCharArray();
        
        for(int i = 0; i < a.length(); i ++){
            if(A[i] != B[i]){
                res ++;
                if(B[i + 1] == '*') B[i + 1] = 'o';
                else B[i + 1] = '*';
            }
        }
        
        System.out.print(res);
    }
}

 

116. 飞行员兄弟 - AcWing题库

暴力枚举所有方案(0 ~ 2^16 - 1),按照该方案对所有开关进行操作,然后判断,记录方案 

import java.util.*;

class PII{
    int x, y;
    public PII(int x, int y){
        this.x = x;
        this.y = y;
    }
}

public class Main{
    static int N = 5;
    static char[][] g = new char[N][N];
    static char[][] backup = new char[N][N];
    //找到每个位置的编号
    public static int get(int x, int y){
        return 4 * x + y;
    }
    
    //改变同一行同一列元素的状态
    public static void turn_all(int x, int y){
        for(int i = 0; i < 4; i ++){
            turn_one(x, i);
            turn_one(i, y);
        }
        turn_one(x, y);
    }
    
    //具体的改变函数
    public static void turn_one(int x, int y){
        if(g[x][y] == '+') g[x][y] = '-';
        else g[x][y] = '+';
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        //输入数据
        for(int i = 0; i < 4; i ++){
            String s = sc.next();
            for(int j = 0; j < 4; j ++){
                g[i][j] = s.charAt(j);
            }
        }
        
        List<PII> res = new ArrayList<>();//用来记录最终路径
        for(int k = 0; k < 1 << 16; k ++){
            List<PII> temp = new ArrayList<>();
            
            //备份
            for(int i = 0; i < 4; i ++){
                backup[i] = g[i].clone();
            }
            
            for(int i = 0; i < 4; i ++){
                for(int j = 0; j < 4; j ++){
                    if((k >> get(i, j) & 1) == 1){
                        temp.add(new PII(i, j));//记录路径
                        turn_all(i, j);//改变同一行同一列元素的状态
                    }
                }
            }
            
            boolean flag = true;//检查开关是否都打开了
            for(int i = 0; i < 4; i ++){
                for(int j = 0; j < 4; j ++){
                    if(g[i][j] == '+'){
                        flag = false;
                    }
                }
            }
            
            if(flag){
                if(res.size() == 0 || res.size() > temp.size()) res = temp;//如果还没有合法值,或者当前值比合法值小
            }
            
            //复原
            for(int i = 0; i < 4; i ++){
                g[i] = backup[i].clone();
            }
        }
        
        System.out.println(res.size());
        for(PII i: res){
            System.out.println((i.x + 1) + " " + (i.y + 1));
        }
    }
}

 

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值