Java 寻找';N';和等于';M';?

Java 寻找';N';和等于';M';?,java,algorithm,random,Java,Algorithm,Random,对于给定的问题陈述,什么必须是有效的算法?(首选java) 求一个由N个数字组成的集合S,使其总和等于M。集合S中的每个数字必须在给定的与平均M/N的偏差“D”范围内 int M= 100; int N= 10; int D= 3; 此处M/N的平均值=10。如果偏差为3,N可以是{7,8,9,10,11,12,13}中的一个数 结果必须与此集合相似: 11 11 9 8 11 9 11 9 10 下面是我到目前为止提出的计划: public class RandomNumberGen

对于给定的问题陈述,什么必须是有效的算法?(首选java)

求一个由N个数字组成的集合S,使其总和等于M。集合S中的每个数字必须在给定的与平均M/N的偏差“D”范围内

int M= 100;
int N= 10;
int D= 3;
此处M/N的平均值=10。如果偏差为3,N可以是{7,8,9,10,11,12,13}中的一个数

结果必须与此集合相似:

11 11 9 8 11 9 11 9 10

下面是我到目前为止提出的计划:

    public class RandomNumberGenerator {

    public static void main(String args[]) {
        Random r = new Random();
        int sum = 100;
        int numbers = 10;
        int deviation = 3;

        int iterator = 0;
        int sumTemp = 0;
        int storeArray[] = new int[numbers];
        int average = Math.round((float) sum / (float) numbers);
        int numberOfAttempts = 0;
        int discardedBecauseGreater = 0;
        System.out.println("Average is " + average);

        while (iterator < numbers) {
            int temp = r.nextInt(average + deviation);
            if (temp > average - deviation) {
                storeArray[iterator] = temp;
                sumTemp += temp;
                iterator++;
            }
            if (iterator == numbers) {
                if (sumTemp == sum) {
                    System.out.println("Got the result " + sumTemp);
                    System.out
                            .println("Number of attempts " + numberOfAttempts);
                    System.out.println("Discarded because of greater "
                            + discardedBecauseGreater);
                    for (int i = 0; i < numbers; i++) {
                        System.out.println(storeArray[i]);
                    }

                    break;
                } else {
                    numberOfAttempts++;
                    sumTemp = 0;
                    iterator = 0;
                }
            }

            if (sumTemp > sum) {
                discardedBecauseGreater++;
                sumTemp = 0;
                iterator = 0;
            }

        }
    }
}
公共类RandomNumberGenerator{
公共静态void main(字符串参数[]){
随机r=新随机();
整数和=100;
整数=10;
内偏差=3;
int迭代器=0;
int-sumTemp=0;
int storeArray[]=新的int[number];
整数平均=数学四舍五入((浮点)和/(浮点)数);
int numberofthresents=0;
int丢弃,因为分离器=0;
System.out.println(“平均值为”+平均值);
while(迭代器<数字){
内部温度=r.nextInt(平均+偏差);
如果(温度>平均值-偏差){
storeArray[iterator]=temp;
sumTemp+=温度;
迭代器++;
}
if(迭代器==数字){
if(sumTemp==sum){
System.out.println(“得到结果”+sumTemp);
系统输出
.println(“尝试次数”+尝试次数);
System.out.println(“由于更大的错误而被丢弃”
+丢弃(因为分离器);
对于(int i=0;isum){
丢弃,因为分离器++;
sumTemp=0;
迭代器=0;
}
}
}
}

<代码> > P> OK,让我们重新考虑这个问题:样本<代码> N<代码>值席,以便:

    SUMIN席= 1
  • 平均值E[Xi]=1/N
  • <席>从<中的每个XI符合+-<代码> d>代码>
如果您能够对这些数字进行采样,那么您可以将其重新缩放到所需的
M

这里描述的是一些大参数。假设我们使用Dirichlet分布,所有αi都等于相同的值
a
。以上连结如下:

  • αi=a
  • α0=N*a
  • E[Xi]=αi/α0=a/(Na)=1/N
  • Var[Xi]~αi/α02=1/(N2a)
因此,如果
a
足够大,方差将非常小。请看右上角图片中的(7,7,7)案例链接。对于最终调整,我们可能会使用接受/拒绝-如果任何值超过
d
的方式,我们会将其丢弃并重新采样

代码(实际上,我的Java已经生锈了)。对于Dirichlet分布的采样,我使用的是众所周知的方法,Java的Gamma分布假定来自Apache公共库


< >好,让我们重新考虑这个问题:样本<代码> n>代码>值席,以便:

    SUMIN席= 1
  • 平均值E[Xi]=1/N
  • <席>从<中的每个XI符合+-<代码> d>代码>
如果您能够对这些数字进行采样,那么您可以将其重新缩放到所需的
M

这里描述的是一些大参数。假设我们使用Dirichlet分布,所有αi都等于相同的值
a
。以上连结如下:

  • αi=a
  • α0=N*a
  • E[Xi]=αi/α0=a/(Na)=1/N
  • Var[Xi]~αi/α02=1/(N2a)
因此,如果
a
足够大,方差将非常小。请看右上角图片中的(7,7,7)案例链接。对于最终调整,我们可能会使用接受/拒绝-如果任何值超过
d
的方式,我们会将其丢弃并重新采样

代码(实际上,我的Java已经生锈了)。对于Dirichlet分布的采样,我使用的是众所周知的方法,Java的Gamma分布假定来自Apache公共库


我认为这个问题与倒水问题类似

您可以选择n个容量为m{i}的杯子来倒入所需的水量

因此,选择“n”个数字求和为“m”

您可以找到解决方案并根据您的用例进行跟踪

以下是一种可能的解决方案:


我认为这个问题与倒水问题类似

您可以选择n个容量为m{i}的杯子来倒入所需的水量

因此,选择“n”个数字求和为“m”

您可以找到解决方案并根据您的用例进行跟踪

以下是一种可能的解决方案:


当前公式可能与FYI重复
{10,10,10,10,…}
是最简单的解决方案。@JohnColeman它不是子集和(我假设它是您所指的NP完全问题),因为您可以自己在一定范围内计算出数字,而不是从集合中选择,虽然这个问题在现阶段还没有得到很好的解释,但最简单的解决方案是用当前公式
{10,10,10,10,…}
对FYI进行可能的重复。@JohnColeman它不是子集和(我假设这是您所指的NP完全问题)因为你可以在一定范围内自己计算出数字,而不是从集合中选取数字,尽管在这个阶段这个问题似乎没有得到很好的解决。
GammaDistribution[] initDirichlet(double a, int N) {
    GammaDistribution[] r = new GammaDistribution[N];
    double scale = 1.0;
    for(int k = 0; k != N; ++k)
        r[k] = new GammaDistribution(a, 1.0);
    }
    return r;
}

void sampleDirichlet(double[] r, GammaDistribution[] g, int N) {
    double s = 0.0;
    for (int k = 0; k != N; ++k) {
        double v = g[k].sample();
        r[k] = v;
        s += v;
    }
    s = 1.0 / s;
    for (int k = 0; k != N; ++k) {
        r[k] *= s;
    }
}

void sample(double[] r, GammaDistribution[] g, int N, double d) {
    double mean = 1.0/(double)N;
    outer:
    for( ;; ) {
        sampleDirichlet(r, g, N);
        for (int k = 0; k != N; ++k) {
            if (Math.Abs(r[k] - mean) > d)
                continue outer; // reject and start over
        }
        break; // accept
    }
}

int use() {
    int N = 10;
    double a = 7.0;
    double d = 0.05;
    GammaDistribution[] g = initDirichlet(a, N);

    double[] r = new double[N];

    sample(r, g, N, d);
    sample(r, g, N, d);
    sample(r, g, N, d);
    sample(r, g, N, d);
    sample(r, g, N, d);
    ....
}