n个骰子的和为S

题目

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=kxi>=1 解的个数分析
主要解决技巧是“挡板法”
举例:
k 个相同的球放入 n 个盒子中,有多少种方法?每个盒子最少一个
解决思路:
k 个求排成一列,有 k1 个空格
下面的任何就是在这个 k1 个空格中合适的位置进行划分
需要分成 n 份,对应 n1 个挡板
所有从 k1 个空格中选取 n1 个位置放置挡板,放置方式数就是解的个数

(k1n1)

x1+x2+...+xn=kxi>=1
解的个数: (k1n1)

那么
x1+x2+...+xn=kxi>=0 解的个数?
两边同时加上 n
x1+1+x2+1+...+xn+1=k+nxi+1>=1
解的个数: (n+k1n1)=(n+k1k)

那么
x1+x2+...+xn=kxi>=a 解的个数?
两边同时减去 na
x1a+x2a+...+xna=knaxia>=0

解的个数: (kna+n1kna)

那么
x1+x2+...+xn=kb>=xi>=a 解的个数?

x1+x2+...+xn=kxi>=a
解的个数: (kna+n1kna)

x1+x2+...+xn=kxi>=b+1
解的个数: (kn(b+1)+n1kn(b+1))

所有
x1+x2+...+xn=kb>=xi>=a 解的个数
(kna+n1kna)(kn(b+1)+n1kn(b+1))

所有:如果n个骰子的和是k,骰子的组合个数就对于方程
x1+x2+...+xn=k6>=xi>=1 解的个数
(kn+n1kn)(k7n+n1k7n)
=(k1kn)(k6n1k7n)
根据上式发现推导有问题, b>=xi>=a 解的个数有问题

待完善

你可能感兴趣的:(n个骰子的和为S)