题目
n个骰子仍在地上,所有骰子朝上一面的和,求出和为K的所有可能组合方式
解题
区分骰子标号
比如:1+2+3 = 5,与1+3+2 = 5是两种方式
转换成数学表达式:
x1+x2+...+xn=k
s.t.xi={1,2,3,4,5,6},i=1,..,n
深度优先遍历
先对
x1
遍历1到6,再
x2
,再
x3...
public ArrayList<String> nSumk(int n,int k){
String list = "";
ArrayList<String> result = new ArrayList<String>();
if(n<=0 || k< n || k > n*6 ) // 非法输入
return result;
DFS(n,1,k,result,list);
return result;
}
public void DFS(int n,int start,int k,
ArrayList<String> result,String list){
if(list.length() == n && k==0){
result.add(new String(list));
return;
}
for(int j=1;j<=6;j++){
if(k-j<0)
return;
k -=j;
list += j;
DFS(n,start+1,k,result,list );
k +=j;
list = list.substring(0,list.length() - 1);
}
}
k -=j;
list += j;
DFS(n,start+1,k,result,list );
k +=j;
list = list.substring(0,list.length() - 1);
上面五行代码可以换成下面一行代码
上面的更新和回溯过程是分开的,下面更新对下一层没有影响
上面有两个回溯,容易遗漏,出错
DFS(n,start+1,k-j,result,list + j);
对于
x1+x2+...+xn=k,xi>=1
解的个数分析
主要解决技巧是“挡板法”
举例:
k
个相同的球放入
解决思路:
k
个求排成一列,有
下面的任何就是在这个
k−1
个空格中合适的位置进行划分
需要分成
n
份,对应
所有从
k−1
个空格中选取
n−1
个位置放置挡板,放置方式数就是解的个数
(k−1n−1)
x1+x2+...+xn=k,xi>=1
解的个数:
(k−1n−1)
那么
x1+x2+...+xn=k,xi>=0
解的个数?
两边同时加上
n
解的个数:
(n+k−1n−1)=(n+k−1k)
那么
x1+x2+...+xn=k,xi>=a
解的个数?
两边同时减去
na
x1−a+x2−a+...+xn−a=k−na,xi−a>=0
解的个数: (k−na+n−1k−na)
那么
x1+x2+...+xn=k,b>=xi>=a
解的个数?
x1+x2+...+xn=k,xi>=a
解的个数:
(k−na+n−1k−na)
x1+x2+...+xn=k,xi>=b+1
解的个数:
(k−n(b+1)+n−1k−n(b+1))
所有
x1+x2+...+xn=k,b>=xi>=a
解的个数
(k−na+n−1k−na)−(k−n(b+1)+n−1k−n(b+1))
所有:如果n个骰子的和是k,骰子的组合个数就对于方程
x1+x2+...+xn=k,6>=xi>=1
解的个数
(k−n+n−1k−n)−(k−7n+n−1k−7n)
=(k−1k−n)−(k−6n−1k−7n)
根据上式发现推导有问题,
b>=xi>=a
解的个数有问题
待完善