鸣人的影分身 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]);
}
}
}