我在混合工厂生产了12种产品(称之为a-l),需要产生不同百分比的产品,总产量明显加起来为100%。
如下面的代码这样的简单方法可行,但效率非常低。有更高效的算法吗?
*编辑:如下所述,有效或无效计算可能性太多。我将此更改为仅混合中最多5个或12个产品,然后根据从12个产品中选择5个产品的方式运行它。
有些人指出的Python代码似乎可以解决组合中的可能性。但是我的Python很小(即0%),你们其中一个人能用Java来解释这个吗?我可以用Java(http://www.cs.colostate.edu/~cs161/Fall12/lecture-codes/Subsets.java)
获得组合public class Main {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
for(int a=0;a<=100;a++){
for(int b=0;b<=100;b++){
for(int c=0;c<=100;c++){
for(int d=0;d<=100;d++){
for(int e=0;e<=100;e++){
for(int f=0;f<=100;f++){
for(int g=0;g<=100;g++){
for(int h=0;h<=100;h++){
for(int i=0;i<=100;i++){
for(int j=0;j<=100;j++){
for(int k=0;k<=100;k++){
for(int l=0;l<=100;l++){
if(a+b+c+d+e+f+g+h+i+j+k+l==100)
{
System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f+" "+g+" "+h+" "+i+" "+j+" "+k+" "+l);
}}}}}}}}}}}}}
}
}
答案 0 :(得分:1)
为什么要这么难。想想简单的方法。
为了简化场景,请考虑随机生成5个数字。伪代码应该如下所示。
答案 1 :(得分:0)
请不要使用嵌套的for循环!改为使用递归:
public static void main(String[] args) {
int N = 12;
int goal = 100;
generate(N, 0, goal, new int[N]);
}
public static void generate(int i, int sum, int goal, int[] result) {
if (i == 1) {
// one number to go, so make it fit
result[0] = goal - sum;
System.out.println(Arrays.toString(result));
} else {
// try all possible values for this step
for (int j = 0; j < goal - sum; j++) {
// set next number of the result
result[i-1] = j;
// go to next step
generate(i-1, sum + j , goal, result);
}
}
}
请注意,我仅针对N = 3
和goal = 5
对此进行了测试。尝试生成所有这些可能性是绝对没有意义的(并且需要永远计算)。
答案 2 :(得分:0)
for(int a=0;a<=100;a++){
for(int b=0;b<=50;b++){
for(int c=0;c<=34;c++){
for(int d=0;d<=25;d++){
for(int e=0;e<=20;e++){
for(int f=0;f<=17;f++){
for(int g=0;g<=15;g++){
for(int h=0;h<=13;h++){
for(int i=0;i<=12;i++){
for(int j=0;j<=10;j++){
for(int k=0;k<=10;k++){
for(int l=0;l<=9;l++){
if(a+b+c+d+e+f+g+h+i+j+k+l==100)
{
// run 12 for loops for arranging the
// 12 obtained numbers at all 12 places
}}}}}}}}}}}}}
在原始方法(基于置换)中,迭代次数为102 ^ 12 = 1.268e24。即使第102次迭代是错误的,它也确实检查了第102次循环终止条件。 所以你在“for”循环中进行了102 ^ 12条件检查,除了“if”条件检查101 ^ 12次,总共2.4e24条件检查。
在我的解决方案(基于组合)中,对于外部12个循环,for循环检查的数量减少到6.243e15,&amp;
如果条件检查= 6.243e15。
现在,对于每个真正的“if”条件,for循环(即内部12循环)的no是12 ^ 12 = 8.9e12。
如果条件允许有x个真值。总状况检查
=没有内部for循环* x
= 8.9e12 * x + 6.243e15
我无法找到x的值。但是,我认为它不足以使总条件检查大于2.4e24
答案 3 :(得分:0)
让我们评论一下,你只能组合5个元素,其他7个是0%。试试这个:
for (i = 0; i < (1<<12); ++i) {
if (count_number_of_1s(i) != 5) { continue; }
for (j = 0; j < 100000000; ++j) {
int [] perc = new int[12];
int val = j;
int sum = 0;
int cnt = 0;
for (k = 0; k < 12; ++k) {
if (i & (1 << k)) {
cnt++;
if (cnt == 5) {
perc[k] = 100 - sum;
}
else {
perc[k] = val % 100;
val /= 100;
}
sum += perc[k];
if (sum > 100) { break; }
}
else { perc[k] = 0; }
}
if (sum == 100) {
System.out.println(perc[0] + ...);
}
}
}
外部循环遍历使用12个项目的所有可能组合。您可以通过循环遍历1:2 ^ 12的所有数字来完成此操作,并且该数字的二进制表示中的1是您正在使用的元素。 count_number_of_1s
是一个循环遍历参数中所有位并返回1
个数的函数。如果这不是5,那么就跳过这个迭代,因为你说你最多只想要5个混合。 (有792个这样的案例)。
j
循环遍历0:100中4个(非5个)项目的所有组合。有100 ^ 4个这样的案例。
内部循环遍历所有12个变量,对于i
中位数为1的那些变量,则表示您正在使用该变量。您可以通过从j
获取接下来的两位小数来计算百分比。对于第5项(cnt==5
),您不需要数字,您可以通过从100减去来计算数字。
这将花费很长时间(分钟),但它不会像12个嵌套循环那样糟糕。