有一组数,共十个:1,2,... 10
要"随机"地分成两组,每组5个
并且两组数和之比在一区间内,比如(0.5,1.5)
比如一组为1,3,5,7,9,另一组为2,4,6,8,10
则两组数和之比是25/30=5/6问如何"随机"地分成两组?

解决方案 »

  1.   

    先用Random类,产生5个爱1-5之间的随机数,在用一个数组来存放10个数字,把数组中没有前五个数的取出来就把他们随机分组了撒。在用循环来使上面的满足他们的比直在你要的区间里撒。
      

  2.   

    这个像洗排一样,对十个元素的数组,产生0~9的随机下标x,循环几次,随便选个十次吧,每次交换a[x]与a[9-x]。随机混排后,取前5个元素之和与后5个元素之和相除就行了,如果比值在不属于要求的区间内,再进行一次混排,求比值,直到符合条件为止。
      

  3.   

    回Inhibitory:机率是相等,不过他是要用随机来得到某一结果,方法显然不可取.就像一副牌,你随机了n多次,取到了不同的53张,就差一张"草花5"了,随机取怎么取得到啊?概率小于0.03的算是异常事件.这时要用穷举,不能用随机
      

  4.   

    回复人:justicesun(结贴点管理!) 
    不玩嘴皮子上那些虚的,看程序结果才是王道:
    #include <stdio.h>
    #include <iostream>
    #include <cmath>
    #include <ctime>using namespace std;int main() {
        const int length = 15; // 数组长度
        int array[length];
        
        srand(time(0));
        cout << "随机分配 " << length << " 个数" << endl;
        for (int i = 0; i < length; i++) {
            array[i] = rand() % 30;  // 分配随机数 
            cout << array[i] << "\t";
        }
        
        int times = 20;
        bool flag = true; // 如果flag为false,则混排成功
        while (flag) {
                for (int i = 0; i < times; i++) {
                    // 把数组中的数字顺序打乱
                    int k = rand() % length; // k为0~length-1
                    int temp = array[k];
                    array[k] = array[length - 1 - k];
                    array[length - 1 - k] = temp;
                } 
                
                int sum1 = 0; // 前 length / 2 个数的和
                int sum2 = 0; // 后 length - length / 2 个数的和
                for (int i = 0; i < length / 2; i++) {
                    sum1 += array[i];
                }
                for (int i = length / 2; i < length; i++) {
                    sum2 += array[i];
                }
                
                float ratio = (float)sum1 / (float)sum2;
                if (ratio > 0.5 && ratio < 1.5) {
                   flag = false;
                           
                   // 输出混排后的数组元素
                   cout << endl << "混排成功后数组元素的顺序为:" << endl;
                   for (int i = 0; i < length; i++) {
                       cout << array[i] << "\t";
                   }
                   
                   cout << endl << "前 " << length / 2 << " 个数之和与后 " << (length - length / 2)
                        << "个数之和的比是 " << ratio << endl;
                }
        }
    }随机分配 10 个数
    28      29      2       27      16      4       21      19      22      14
    混排成功后数组元素的顺序为:
    14      29      2       21      16      4       27      19      22      28
    前 5 个数之和与后 5个数之和的比是 0.82随机分配 15 个数
    26      28      28      25      26      13      25      1       21      8
    20      15      5       13      25
    混排成功后数组元素的顺序为:
    26      28      5       15      26      13      25      1       21      8
    20      25      28      13      25
    前 7 个数之和与后 8个数之和的比是 0.978723
    随机分配 25 个数
    10      17      15      11      28      0       24      2       17      4
    22      29      6       2       11      23      23      20      19      28
    24      7       14      22      26
    混排成功后数组元素的顺序为:
    26      17      14      7       24      0       19      20      17      23
    22      2       6       29      11      4       23      2       24      28
    28      11      15      22      10
    前 12 个数之和与后 13个数之和的比是 0.896714
      

  5.   

    把那个length 改成从命令行输入,然后为数组array动态分配内存,最后记得释放内存,这样,每次改length时,都不用重新编译了。
    int length = 10;
    cout << "输入length: " << endl;
    cin >> length;
    int* array = NULL;
    array = new int[length];
    .
    .
    .
    delete[] array;
      

  6.   

    感谢各位积极参与讨论!回justicesun:由于实际应用中是100多个数分成两组,组合太多,穷举恐怕不行吧
    回Inhibitory:我的十个数是1,2...10,你为何改成其他数?偶看这样行吗:先随机分成两组,如果比值不在区间内(由于第一组数偏大),则在第一组中"任"选一个较大的数与第二组中"任"一个较小的数交换,如果还不行,再换问题:以上算法会使比值落在区间边界附近的可能性偏大如何改进?
      

  7.   

    Inhibitory一付排里有四张“草花5”这种话你也说得出,你玩百家乐还是麻将啊?
      

  8.   

    1: 把10个数放 到数组里
    2: 生成随机数,范围0~9,取整;
    3: 临时下标=生成的随即数
    4: 按临时下标从数组取数字
    5: 如果该数字是0,临时下标++,临时下标除10取余,回到4
    6: 如果该数字不是0,表示成功获得,把数字保存到另一个数组A,同时把原数组里该位置置0
    7: 重复5次
    8: 遍历一遍原数组,把非零的数字保存到数组BA B就是随机分出的数组
      

  9.   

    上面算法不好,换个:
    1: 把10个数放 到数组里,初始范围 max=10;
    2: 生成随机数,范围0~max,取整;
    3: 临时下标=生成的随即数
    4: 交换临时下标和下标是max的数据;
    5: max--;
    6: 重复2~5  次前5个和后5个分别就是 需要的两组数据
      

  10.   

    jihanzhong(逍遥)的方法 不错 对于100个数随机,只需要把十位数 和个位数嵌套循环一下就可以了,LZ参考一下
      

  11.   

    回jihanzhong(逍遥):偶要求两组数的和之比在一区间中,你的算法怎么没提到这个比值?
      

  12.   

    先随机分成两组,如果比值不在区间内(由于第一组数偏大),则在第一组中"任"选一个较大的数与第二组中"任"一个较小的数交换,如果还不行,再换问题:以上算法会使比值落在区间边界附近的可能性偏大如何改进?
    ========================================================1。1 到 k 的数,和为 sum,分成两组,它的比率在 (d1, d2) 之间,就可以获得它们每组和的最大值和最小值。  min = (int) (sum / ((1 + d1) / d1));
      max = (int) (sum / ((1 + d2) / d2));2。按照楼主所说的,先进行随机分组,求出其中一组的和,或它的和在 (min, max) 之间,就OK 。否则,在 (min, max) 之间随机抽取一个数,得出差值,再与和小的一组小的最小值相加,再到另一组中寻找该数(为方便寻找可以限制正负范围),与那组中的最小值进行交换,若没有找到,继续在 (min, max) 之间随机抽取,重复上述过程。
      

  13.   

    换了一组算法,将原序进数字顺序随机交换,并按前后均余分成两组,求其一组的和,若在限定范围内,则 OK,否则重新分组。import java.util.Random;public class Test {  public static void main(String[] args) {    float d1 = 0.5f;   // 比率下限
        float d2 = 1.5f;   // 比率上限
        int k = 10;      // 数组个数
        int sum = (1 + k) * (k / 2);   // 数组和
        int min = (int) (sum / ((1 + d1) / d1));  // 限定比率的最小和
        int max = (int) (sum / ((1 + d2) / d2));  // 限定比率的最大和
        System.out.println(min + " " + max);    // 生成数字序列
        int[] num = new int[k];
        for (int i = 0; i < k; i++) {
          num[i] = i + 1;
        }    
        System.out.print("原数组:");
        print(num);    int[] group1 = new int[k / 2];
        int[] group2 = new int[k / 2];
            
        int groupSum = 0;  // 存放某一组的和
        Random random = new Random();    
        
        // 若 groupSum 不在 (min, max) 范围内,则重新分组
        while (groupSum < min || groupSum > max) {
          groupSum = 0;      // 通过随机数交换数字,交换次数、交换位数都是随机
          int r = random.nextInt(k * 2);
          for (int i = 0; i < r; i++) {
            int r1 = random.nextInt(k);
            int r2 = random.nextInt(k);
            int tmp = num[r1];
            num[r1] = num[r2];
            num[r2] = tmp;
          }
          System.out.print("交换后:");
          print(num);      // 进行分组,并统计一组的和
          for (int i = 0; i < k / 2; i++) {
            group1[i] = num[i];
            groupSum += num[i];
            group2[i] = num[i + k / 2];
          }
          
          System.out.print("第一组:");
          print(group1);
          System.out.print("第二组:");
          print(group2);
          System.out.println("一组和:" + groupSum);
          System.out.println("二组和:" + (sum - groupSum));
          System.out.println("比 率:" + groupSum / ((float) sum - groupSum));
        }
      }  public static void print(int[] ns) {
        for (int i : ns) {
          System.out.printf("%3d", i);
        }
        System.out.println();
      }
    }