鸣人的影分身 DFS + 打表 + DP

🍑 算法题解专栏


🍑 鸣人的影分身

在这里插入图片描述
输入

1
7 3

输出

8

🍑 暴力搜索(搜索每种方案)

import java.util.*;

class Main{
    static int N = 12,m,n,res;
    
    // x 上一个分身的能量取值,remain 剩余的能量值,cnt 分出的分身数量
    // 注意:这里的搜索是按顺序搜索的
    static void dfs(int x,int remain, int cnt){
        if(cnt == n && remain == 0)
        {
            res++;
            return;
        }
        // 剪枝
        if(cnt >= n || remain <= 0)
            return;
        
        for(int i = x; i <= remain; i++)
            dfs(i,remain-i,cnt+1);
        
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while(T-- >0)
        {
            m = sc.nextInt();
            n = sc.nextInt();
            res = 0;//多组数据记得初始化全局变量
            dfs(0,m,0);
            System.out.println(res);
        }       
    }
}

🍑 暴力搜索(水果分盘)

import java.util.Scanner;

public class Main
{
	static int n, m;

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while (T-- > 0)
		{
			n = sc.nextInt();// n 个苹果
			m = sc.nextInt();// m 个盘子
			System.out.println(get(n, m));
		}
	}

//	x 表示果子数  y 是盘子数 
	private static int get(int x, int y)
	{
		if (y == 0)// 没有盘子,方案数为 0
			return 0;
		if (x == 0)// 没有果子,但是有盘子,每个盘子都为 0,方案数为1
			return 1;
		// 盘子数大于果子数,顶多每个盘子放一个(空盘子随便放都是 0 都是算一种方案)
		if (y > x)
			return get(x, x);

//		分类讨论
//		① (x-y,y):没有空盘子的情况
//		② (x, y - 1):至少有一个空盘子的情况(关键:递归的时候就会计算 1,2,3……个空盘子的情况)
		return get(x - y, y) + get(x, y - 1);
	}
}

🍑 预处理(打表)

import java.util.Scanner;

public class Main
{
	static int N = 11;
	static int[][] a = new int[N][N];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);

		for (int i = 0; i <= 10; i++)// 枚举果子
			for (int j = 0; j <= 10; j++)// 枚举盘子
			{
				if (i < j)//果子不够分
					a[i][j] = a[i][i];
				else if (i == 0)//果子为 0,所谓盘子都放 0 个
				{
					a[i][j] = 1;
				} else if (j == 0)//盘子为0,果子没地放,方案数 为 0
					a[i][j] = 0;
				else
				{
				    //        无空盘         必有空盘
					a[i][j] = a[i - j][j] + a[i][j - 1];
				}
			}

		int T = sc.nextInt();
		while (T-- > 0)
		{
			int m = sc.nextInt();
			int n = sc.nextInt();
			System.out.println(a[m][n]);
		}
	}
}

🍑 DP

import java.util.Scanner;

public class Main
{
	static int N = 12;
	static int[][] f = new int[N][N];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while (T-- > 0)
		{
			int m = sc.nextInt();// 总量
			int n = sc.nextInt();// 份数
			f[0][0] = 1;// 总量为 0,每份都是 0 单位(不管分没分),就是 1 种方案
			for (int i = 0; i <= m; i++)// 枚举总量
				for (int j = 1; j <= n; j++)// 枚举份
				{
					f[i][j] = f[i][j - 1];
					if (i >= j)
						f[i][j] += f[i - j][j];// i-j 即给每份都 分了1单位 的情况
				}
			System.out.println(f[m][n]);
		}
	}
}
posted @ 2023-04-25 15:38  兑生  阅读(12)  评论(0编辑  收藏  举报  来源
Live2D