把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
解题思路:看到这道题目,首先想到的是数学里的排列组合的插空法,即将N个盘子插到M+1个位置。首先将第N个盘子固定在第M+1个位置,然后其余每个盘子都有M种可能,递归调用,去除不合格的结果,即为所求。
总结:看网上别人都是通过递推式求解的,效率很高。相比之下,我的解法过于注重插空反而忽视了其本身的递推规律,导致计算了大量的重复结果,效率不高,但是还是留下来做个纪念吧,以后还是要勤加练习。
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
static int k=0;
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int m=scanner.nextInt();
int n=scanner.nextInt();
int result=count(m,n);
System.out.println(result);
scanner.close();
}
public static int count(int m, int n){
if(m<0||m>10)
return -1;
if(n<1||n>10)
return -1;
if(n>m)
return -1;
Set<String> list=new HashSet<String>();
int[] a=new int[n];
int[] result=new int[n];
a[n-1]=m;
int k=0;
fun(m,n,k,a,result,list);
return list.size();
}
public static void fun(int m,int n,int k,int[] a,int[] result,Set<String> list){
a[n-1]=m;
String temp="";
if(k==n-1){
for(int i=0;i<n;i++){
if(i==0){
result[i]=a[i];
}else{
result[i]=a[i]-a[i-1];
if(result[i]<0) //筛掉不合格结果
return;
}
}
Arrays.sort(result);
for(int i=0;i<n;i++){
temp=temp+result[i]+"";
}
list.add(temp);
return;
}
for(int i=0;i<=m;i++){
a[k]=i;
fun(m,n,k+1,a,result,list);
}
}
}