给定整数n,取若干个1到n的整数可求和等于整数m,编程求出所有组合的个数。
比如当n=6,m=8时,有四种组合:[2,6], [3,5], [1,2,5], [1,3,4]。限定n和m小于120
动态规划
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
//dp[i]: 从[1, ..., n]中取若干个数求和等于m的组合的个数
int[] dp = new int[m + 1];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= i; j--) {
dp[j] += dp[j - i];
}
}
System.out.println(dp[m]);
}
}
另一种循环
// dp[i][j]表示最大值为i,和为j的组合个数
int[][] dp = new int[n + 1][m + 1];
for (int row = 0; row <= n; row++) {
dp[row][0] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
// get dp[i][j]
if (i > j) {
dp[i][j] = dp[j][j];
continue;
}
dp[i][j] += dp[i - 1][j] + dp[i - 1][j - i];
}
}
0-1背包问题思想
//0-1背包问题 f(n,m) 转化为两个子问题 f(n-1,m) 和 f(n-1,m-n)
public static int getCount(int n, int m){
if(m<1 || n<1) return 0;
if(m<n) n=m;
int sum=0;
if(m==n) sum++;
//不选中n
sum+=getCount(n-1,m);
//选中n
sum+=getCount(n-1,m-n);
return sum;
}