我写了一个生成子集和的程序,可以用于解决以下问题:
假设你有3个1美元硬币、2个2美元硬币、3个5美元硬币和1个10美元硬币,那么有4种方法可以从这些硬币中获得10美元。如果有n1个X1硬币、n2个X2硬币... nm个Xm硬币,我们可以用这些有限数量的硬币获得多少种方法来获得X美元呢?
如果我们创建一个集合{X1,X1 ..... X1,X2,X2 .......... X2,......,......,............,Xm,Xm ... Xm},然后在其上运行子集求和,我们肯定可以得到X美元的结果。但我找不到使用集合{n1,n2,n3 ... nm},{X1,X2,X3 ... Xm}的方法。一位朋友告诉我这是背包问题的变体,但我不确定如何解决。
这是我所写代码的一部分:
如果您能详细解释一下,那就太好了。 编辑: 这个问题更适合计算机科学的stackexchange,但由于这是我的一个旧问题,我宁愿在这里进行编辑。 使用包含排除原理可以解决这个问题,在每个查询中硬币价值固定但每种硬币数量不同时非常方便。假设,ways[v]表示用$x1$,$x2$,... $xm$制作$v$的方法,每个方法被使用多次。现在,如果我们只使用$n1$个$x1$数,则必须减去至少使用($n1$ + 1)个$x1$的配置(实际上是ways[v - (n1 + 1)x1])。此外,如果我们只使用$n2$个$x2$数,则还必须减去ways[v - (n2 + 1)x2],以此类推。现在,我们两次减去了至少使用($n1$ + 1)$x1$和($n2$ + 1)$x2$的配置,因此我们需要添加ways[v -(n1 + 1)x1 - (n2 + 1)x2]等。特别地,如果, N = 使用尽可能多的所有硬币的配置集,Ai = 至少使用ni+1个$xi$的配置集,对于1<=i<=m,则我们要寻找的结果= |N| − |A1| −| A2| ... - |Am| + | A1和A2| + | A1和A3| + ... - | A1和A2和A3| ... 计算具有无限硬币数量的配置数的代码实际上更简单:
假设你有3个1美元硬币、2个2美元硬币、3个5美元硬币和1个10美元硬币,那么有4种方法可以从这些硬币中获得10美元。如果有n1个X1硬币、n2个X2硬币... nm个Xm硬币,我们可以用这些有限数量的硬币获得多少种方法来获得X美元呢?
如果我们创建一个集合{X1,X1 ..... X1,X2,X2 .......... X2,......,......,............,Xm,Xm ... Xm},然后在其上运行子集求和,我们肯定可以得到X美元的结果。但我找不到使用集合{n1,n2,n3 ... nm},{X1,X2,X3 ... Xm}的方法。一位朋友告诉我这是背包问题的变体,但我不确定如何解决。
这是我所写代码的一部分:
ways[0]=1, mylim=0;
for(i=0;i<count;i++){
if(mylim+coins[i]<=LIMIT) mylim+=coins[i];
else mylim=LIMIT;
for(j=mylim; j>=coins[i];j--){
ways[j]=(ways[j]+ways[j-coins[i]])%MOD;
}
}
如果您能详细解释一下,那就太好了。 编辑: 这个问题更适合计算机科学的stackexchange,但由于这是我的一个旧问题,我宁愿在这里进行编辑。 使用包含排除原理可以解决这个问题,在每个查询中硬币价值固定但每种硬币数量不同时非常方便。假设,ways[v]表示用$x1$,$x2$,... $xm$制作$v$的方法,每个方法被使用多次。现在,如果我们只使用$n1$个$x1$数,则必须减去至少使用($n1$ + 1)个$x1$的配置(实际上是ways[v - (n1 + 1)x1])。此外,如果我们只使用$n2$个$x2$数,则还必须减去ways[v - (n2 + 1)x2],以此类推。现在,我们两次减去了至少使用($n1$ + 1)$x1$和($n2$ + 1)$x2$的配置,因此我们需要添加ways[v -(n1 + 1)x1 - (n2 + 1)x2]等。特别地,如果, N = 使用尽可能多的所有硬币的配置集,Ai = 至少使用ni+1个$xi$的配置集,对于1<=i<=m,则我们要寻找的结果= |N| − |A1| −| A2| ... - |Am| + | A1和A2| + | A1和A3| + ... - | A1和A2和A3| ... 计算具有无限硬币数量的配置数的代码实际上更简单:
ways[0]=1;
for( int i = 0 ; i < count ; i++){
for( int j = coins[i] ; j < ways.size() ; j++ ){
ways[j] += ways[j-coins[i]];
}
}
Xi
比允许的次数多。 - IVlad