假如有s篇文章,每人审核m篇,每篇n个人审核。
怎么得到需要多少人呢。
例如:
总共有9篇文章(1,2,3,4,5,6,7,8,9),每人3篇,每篇需要3个人审核。
我的算法为:把总文章数s除以每人审核篇数m得到k,然后k乘以每篇n人审核。
算法为:s/m=k*n,如果sm的余数不为零,那么k=k+1然后再乘以n;
上面的例子结果如下:
论文:(123),(456),(789)把论文分成等三份。每份三个人,所以需要9个人。
假如有10篇论文,那么就需要12个人了。(123),(456),(789),(10)分成了四份。
还有,具体到分配的时候怎么保证每个人的论文都不一样呢,上面的结果是每三个人的论文完全一样的。
大家有没有别的好的算法呢。相当的考脑力哦。。

解决方案 »

  1.   

    S*N = R*M
    S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数
    工作量=S*N=R*M
      

  2.   

    terry_12(大撒发射点)你的算法不正确啊。
      

  3.   

    n=(S*N)/M
    文章审核量是S*N,除以M就行
    小学3年级
      

  4.   

    kingkiosk() 
    你的考虑太片面。
      

  5.   

    private int GetNum(double s,double m,double n)
    {
    s = Math.Ceiling(s/n)*n;
    int r = Convert.ToInt32(s*n/m);
    return r;
    }
    S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数
    工作量=S*N=R*M
      

  6.   

    感觉terry_12(大撒发射点)的算法是对的,
    S*N = R*M
    S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数R=S*N/M这样算,9篇需要9人,10篇则需要10人。至于具体的分配就可能比较复杂了。
      

  7.   

    其实有问题的..小于3的时候就不对了.
    小于3的时候s = Math.Ceiling(s/n)*n;
    没怎么考虑清楚..
    下班回家吃饭..YEAH
      

  8.   

    这个问题用if解决.
    IF小于3的时候用另外的算法
      

  9.   

    private int GetNum(double s,double m,double n)
    {
    s = Math.Ceiling(s/n)*n;
    int r = Convert.ToInt32(s*n/m);
    return r;
    }
    S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数
    工作量=S*N=R*M
    这个算法还是有问题的。当s=9,m=4,n=3就不对了吧。这个时候应该是8个。
      

  10.   

    简单点说
    用一个数组A[s*m]放需要审记的东西
    for(i=0,i<s*m,i++) 
    A[i]=i%m;
    /*A[i]里面放的文件编号,编号由0开始     例如 9篇文章  A[10]=1,放的是1号文件  */
    然后只要这样
    i=0,j=0,k=0;
    while(i<s*m)
     { while(k<n)
         {B[j][k]=s[i]     /*B数组 j代表的是审记人员编号(0开始),k是他的第K份审记文件.*/
           i++;
           k++;
           }
       k=0;
       j++; 
      }  
    j就是需要的人数了
    如果要具体查到哪个人负责哪些
    看一下数组B[j][]就知道了
    这个算法有2个例外
    1:  M>S的时候  每个人审计的东西都会重复
    2:  S<N的时候
      

  11.   

    解释一下我上面的思路
    我是用一个数组放所需要的东西
    拿楼主给的例子
    A[]={0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8}
    那么
    B[0][0]=0,B[0][1]=1,B[0][2]=2  也就是0号审计员需要负责  0,1,2号
    B[1][0]=3,B[1][1]=4,B[1][2]=5   也就是1号审计员需要负责 3,4,5号
    依次类推,直到i=s*m也就是A数组都走了一遍,任务全部完成
      

  12.   

    这个题目如果限制了m,n的值就没有答案
    如果没有限制
    则可以用两个for求出所有的可能
    然后再选择要求人数最少的那个m,n值。
      

  13.   

    这个题目如果限制了m,n的值就没有答案
    如果没有限制
    则可以用两个for求出所有的可能
    然后再选择要求人数最少的那个m,n值。
    ------------------------------------------
    m,n是设定的,不确定的值。
      

  14.   

    说明:s,m,n值都是不确定的值。
      

  15.   

    我给的那个算法是把所有任务放在一个队列里,然后每个人去队列里拿M个任务出来
    这样的话,出现的问题是
    M>S的时候  每个人审计的东西都会重复
    所以,需要的人是S
    每个人的任务都一样,是S次,从0审计到S-1号文件
    我想了一下,S,N没什么问题
      

  16.   

    n=1,m=aaa(s) 
    时,得到最佳答案
    最少人数为:s/mint aaa(int s)
    {
    for(int i=1;i<s/2;)
      {
          int k=0;
          if(s%i==0)
          {   
              k=i;
              i++;
           }
           else
              i++
       }
    return k;
       }
      

  17.   

    private int GetNum(double s,double m,double n)
    {
    s = Math.Ceiling(s/m)*m;  //这里n换成m
    int r = Convert.ToInt32(s*n/m);
    return r;
    }
    不知道这样行不行
      

  18.   

    if( s >= m)
    result=s*n/m;
    else
    result=error;
    文章
    1   2 3 4 5 6 7 .... s
    人员 1 a   b c d e f g .... m
         2 m   a b c d e f .... m-1
         3 m-1 m a b c d e .... m-2
        ...
         n
      

  19.   

    我告诉大家怎么做吧!!首先声明,题目有点问题,应为:   ( 《》内为关键处 )
    每人 《至多》 审核m篇文章,每篇文章 《至少》 需要n人审核。
    有s篇文章,问 《至少》 需要多少人。现在我们分析问题:1.假设有 1  篇文章,有 n 人,且( m>=1  ),则需要 n 人。 (这步总能懂吧 :) )
    2.假设有 _m 篇文章,有 n 人,且( m>=_m ),则需要 n 人。 (n 人是至少的,而且足够:) )
    // 现在人多点,超过 m 人,但 _m<=2*m 
    3.假设有 _m 篇文章,有 n 人,且( m>_m 且 m<=2*m ),则需要 2n 人。(这步理解吗)
      前 n 人处理前 m 篇,后 n 人处理 m-_m 篇4.一般情况呢 ? 我不给具体推导过程,给出个公式 :
                        (s/m)*n             .. 应该能理解吧如果还有问题 :到我的 blog : blog.csdn.net/vic_st
      

  20.   

    想了下,不考虑特殊情况比如M>S,或者S<3这题就是个很简单的r=int(S*N/M)+1至于每个人的论文都不全相同,其实也很好推出比如9,4,3的情况(1,2,3,4)(5,6,7,8)(9,1,2,3)(4,5,6,7)(8,9,1,2)(3,4,5,6)(7,8,9,1)类似这种首尾相连的排列不知道可能的问题出在哪里,~
      

  21.   

    刚才有点看错了,现在给出考虑了楼主 “每人审阅的文章不同”的条件(暂计为 Con(ind))解决:为了方便,用C(m,n) 表示 n 选 m 的组合数。 // C(m,n)=n! / (m! * (n-m)!)
    计人数 为 k 。
    为了 Con(ind), 必须有 k<C(m,s) :(否则必然有两人有相同文章审阅集合)
    不考虑 Con(ind),得 k'=(s/m)*n;因此,有 (s/m)*n<=C(m,s)  .. 可见要满足 Con(ind), 对 n 有一定限制。现在假设有 C(m,s) 人,每人对应 s 选 m 的一种组合。
    则 每篇文章将被审核 C(m,s) * m / s 次。 ( see? )
    上式= C(m-1,s-1) ........明天继续写。
      

  22.   

    S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数N*(S-M*R)>=0代入求R,若R小于等于的值为整数,则该值为所求值;如RR小于等于的值为小数,则在把该数凑整(不能四舍五入)。
      

  23.   

    写错了,重来S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数M*R-N*S>=0代入求R,若R大于等于的值为整数,则该值为所求值;如R大于等于的值为小数,则在把该数凑整(不能四舍五入)。
      

  24.   

    写错了,重来S:总文章
    R:总人数
    N:每篇人数
    M:每人篇数求需要最少人数
    M*R-N*S>=0代入求R,若R大于等于的值为整数,则该值为所求值;如R大于等于的值为小数,则在把该数去余数取整数的基础上加N(不能四舍五入)。
      

  25.   

    简单点,以每遍文章被读的次数建立等式
    n*s=m*x
    s篇文章,审核m篇,每篇n个人审核,x个人
    x=ns/m
    想那么多干吗?
      

  26.   

    public class Check
    {
    public static void main(String [] args){
    int [] book = new int[100];
    int people=0;
    int checkCont=0;
    int i=0; while(true){
    checkCont=0;
    for(i=0;i<book.length;i++){
    if(book[i]<3){
    book[i]++;
    checkCont++;
    }
    if(checkCont>=3){
    people++;
    break;
    }
    } if(checkCont<3&&checkCont>0)
    people++; if(i==book.length&&book[i-1]==3){
    break;
    } } System.out.println("需要人数:"+people);
    }
    }
      

  27.   

    请教一个.net 的问题http://community.csdn.net/Expert/topic/4926/4926790.xml?temp=1.392764E-02
      

  28.   

    假设每人审查了k个,一共有p个人则  t = p
      西格码(k)=s*n
      t=0  p>=n  0<k<m对这个算式些程序就可以了
      

  29.   

    得到p*k’ = s*n
        p〉=n
        0〈k〈=m判断几个变量的临界还不简单~~~
      

  30.   

    一个文章N个人看,这属于制度问题,不可改变,是必须条件;但一个人看M个文章,这属于工作量问题,可以根据实际情况进行整体或部分地调整,当实际情况难以正好分配时就不是必须条件.也就是说S*N是确定的,是需要保证必须满足的总的最少评阅次数.
    而M*R应该是大于等于S*N的,即可能有人没有达到M次工作量.实际分配中,因为几个量都是不定的,极有可能所分配的值不会使每个人都恰巧分配到同样多的文章,或者说,硬要同样多的话,就会出现某些人被重复分到相同文章,相同的不再看也等效于少分配一次),就保证不了每个人所看的M个文章是不相同的.所以这个问题的关键是分清主次,关系就应该是S*N<R*M.
      

  31.   

    有没有人往图的方向想,文章是一个集合,人是一个集合,对应,不过好烦,想ing...
      

  32.   

    假如有s篇文章,每人审核m篇,每篇n个人审核。
    怎么得到需要多少人呢。人数 R = s*n/m
    分配  则是一个排序的问题,排出全序 每个人顺序取就好了,根据题意最后一个人可能没有m篇
      

  33.   

    P(s,n) 的个数是 C(s,1) * C(s-1,1) * (s-2,1) ......C(s-m+1,1)
    申请m个数组,m个指针,每个数组保存全部文章,
    一次移动m个指针中的一个,获得一个组合,
    直到获得全部结果的个数
      

  34.   

    1....s, 1....s, ....., 1.....s
    \________n 个1....s_________/
    每人抽取 m 篇 (m<s)
    ---------------------------------------------------------------
    1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9  
    9篇 每人4篇 每篇3人
    1234   5678 3456  2789  4567 1239 189*
      

  35.   

    楼主的目的是想得到所有可能的组合,可我们这里都在关心最少需要几个人。我觉得theforever(碧海情天) 的分析很对,这个求最少人数的计算其实很简单,关键是求出最少的人之后并不能够保证所有的人都审阅同样多的文章,在不能除尽的情况下必然有个人审阅的文章比其他人要少。
    我想楼主可能就是觉得在这样的情况下求出所有可能的组合比较麻烦吧!
      

  36.   

    文章总数为S * N。S > M假设第一个人来取,总是从最多张数的稿子集合里面抽取最多M张稿子。
    这样人数还是等于 S * N / M,不能除尽则加多一人。
      

  37.   

    如果对每个人的论文都不一样要求不严格的话:
    最简单的算法就是用随机
    就像摇奖那样全部放到一起摇一摇(s*n)。每个人再抽出来哈(m)。毕竟中奖不大容易哈。
      

  38.   

    此题有两个隐含的前提:
    就是n<s和m<s,
    如果不满足这两个条件,
    就不能满足“每个人的文件都不同”这个条件,
    你如果问我为什么,我只能举例来解释:
    我们用边界界定法来讲:
    假设S = 10
    M和N都为极限10,你有办法每个人的文件都不同吗?
    进一步,单独取M或者N为10,另一个任意,能作到吗?
    都不能!
      

  39.   

    每人分配不一样算法  只实现了9/3/3 只要将特定值改为变量 就OK
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>void main( void )
    {
       int i,j=0;
       int r; //随机数
       int *a = new int[81];
       int *p = new int[27];   srand( (unsigned)time( NULL ) );   for(i=0; i<27; i++)
       {
       a[i] = i%9+1;
       a[i+27] = 1;
       a[i+54] = 1;
       p[i] = 0;
       }do
    {
    r = rand()%27;
    if(j%3==0)
    for(i=0; i<27; i++)
    a[i+54] = 1;
    if(a[r+27] == 1 && a[r+54] ==1)
    {
    p[j] = a[r]; 
    a[r+27] = 0;
    a[r%9+54]=a[r%9+9+54]=a[r%9+18+54]=0;
    j++;
    }
    }while(p[j] == 0);
     
       for( i = 0;   i < 9;i++ )
       {
     printf( "%d-%d-%d   ", *(p+i),*(p+i+9),*(p+i+18));
    }   delete p,a;
    }
      

  40.   

    这个问题确实考脑力啊,如果只看你的例子的话,那还好.试想如果每个人都审核的文章必须是不同的m篇的话,那可能是无解的.如果m>n,并且m*n>s的话,就有问题.如果每人最多m篇不同的文章的话,那这个实现就无法用简单的数学公式计算了.我的建议是枚举,不过效率不高,写个循环程序模拟分配的方式去做,至于用不用rand我的理解是,用rand有可能造成这样的算法失败,假使每次rand都到同一个位置,那就麻烦了.
      

  41.   

    总文章:S
    总人数:R
    每人审核:M
    每篇人数:N
    每个人审核的文章序号:SID[M]
    已知:Title[S],M,N
    每编文章需要N个人审核,每个人最多M编文章
    每个人审核的文章编号都不同(特例除外,如M=N=S等)
    求:R
    typedef struct
    {
    int ArticleID[M]; //保存每个人审核的文章编号
    int ArticleNum;//实际上每个人审核的文章数,可能小于M
    }AuditingArticle;void main()
    {
    int R=0; //总人数
    int i,j; //循环变量
    int curPerson=0;//当前分配的最大文件编号
    AuditingArticle* AArticle;//定义所有人及每个人审核的文章编号
    R=(S*N)/M; //取余
    if((S*N)%M)
    R++;//获得需要的最多人数
    AArticle=(AuditingArticle*)malloc(R*sizeof(AuditingArticle));//开内存
    memset(AArticle,0,R*sizeof(AuditingArticle));//清空AArticle变量,全置为0 ,也可以循环赋值置0
    //下面的代码就是分配关键 思想其实很简单
    //把curPerson看成一个循环链表 从不同的位置顺序分配
    for(i=0;i<N;i++) // 把S篇文章分配N次
    {
    for(j=0;j<S;j++) //总文章
    {
    curPerson=curPerson%R;
    AArticle[curPerson].ArticleID[AArticle[curPerson].ArticleNum]=j;
    AArticle[curPerson].ArticleNum++;
    }
    }
    }
    最终的效果是:
    如1.2.3.4.5.6.7.8.9.10.11 每人可审核4篇,每编需3人审核
    Persons=(11*3)/4+1=9;
    Person1:1,10,8,6
    Person2:2,11,9,7
    Person3:3,1,10,8
    Person4:4,2,11,9
    Person5:5,3,1,10
    Person6:6,4,2,11
    Person7:7,5,3
    Person8:8,6,4
    Person9:9,7,5
      

  42.   

    修正:int curPerson=0;//当前分配的人员编号
    开始没有看到foren_whb(丰云)兄的,我解决方法和foren_whb(丰云)兄的
    一样。
    改进1:以上方法很容易推导自己所要审核的文件编号,我们可以增加随机
    跳跃数,这样每个人的文章编号都相当随机,修改后的代码为:
    int Jump=0;
    curPerson=rand()%R; 
    Jump=rand()%(R/2);
    for(i=0;i<N;i++) // 把S篇文章分配N次
    {
    for(j=0;j<S;j++) //总文章
    {
    curPerson=curPerson%R;
    AArticle[curPerson].ArticleID[AArticle[curPerson].ArticleNum]=j;
    AArticle[curPerson].ArticleNum+=Jump;
    }
    }
    }
      

  43.   

    以下给出单向链表解法!!!具体到每个人审阅的篇数可以以人为单位各不相同,具体到每篇审批的人数可以以篇为单位各不相同!!!
    以下定义为11篇每篇3人,每人4篇import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;public class TestAllocation {
        // 人类定义
        private static class Person {
            private int num = 0;
            private String name = null;
            private List books = new ArrayList();
            public Person (String name, int num) {
                this.name = name;
                this.num = num;
            }
            public boolean addBook(Book book) {
                if (books.size()==this.num) return false;
                books.add(book);
                book.num--;
                return true;
            }
            public List getBooks() {
                return this.books;
            }
            public String toString() {
                return this.name;
            }
        }
        // 数类定义
        private static class Book {
            public int num = 0;
            private String name = null;
            public Book (String name, int num) {
                this.name = name;
                this.num = num;
            }
            public String toString() {
                return this.name;
            }
        }
        // 每人审批篇数
        private static int iBook = 4;
        // 每篇审批人数
        private static int iPerson = 3;
        // 书数组定义
        private static Book[] books = new Book[] {new Book("1", iPerson),new Book("2", iPerson),new Book("3", iPerson),new Book("4", iPerson),new Book("5", iPerson),
                                           new Book("6", iPerson), new Book("7", iPerson), new Book("8", iPerson), new Book("9", iPerson),
                                           new Book("10", iPerson), new Book("11", iPerson)
                                          };
        public static void main(String[] args) {
            LinkedList bookList = new LinkedList();
            for (int i = 0; i < books.length; i++) {
                bookList.add(books[i]);
            }
            LinkedList personList = new LinkedList();
            
            int personName = 1;
            while (bookList.size()>0) {
                Person person = new Person(String.valueOf(personName++), iBook);
                while (true) {
                    if (bookList.size()==0) break;
                    Book book = (Book) bookList.removeFirst();
                    if (person.addBook(book)) {
                        if (book.num!=0) bookList.addLast(book);
                        continue;
                    }
                    bookList.addFirst(book);
                    break;
                }
                personList.add(person);
            }
            
            // 结果输出
            Iterator it = personList.iterator();
            while (it.hasNext()) {
                Person person = (Person) it.next();
                System.out.println("Person name: " + person);
                System.out.println("Has Books: ");
                for ( int i = 0; i < person.getBooks().size(); i++) {
                    System.out.println(person.getBooks().get(i));
                }
            }
        }
    }
    结果:
    Person name: 1
    Has Books: 
    1
    2
    3
    4
    Person name: 2
    Has Books: 
    5
    6
    7
    8
    Person name: 3
    Has Books: 
    9
    10
    11
    1
    Person name: 4
    Has Books: 
    2
    3
    4
    5
    Person name: 5
    Has Books: 
    6
    7
    8
    9
    Person name: 6
    Has Books: 
    10
    11
    1
    2
    Person name: 7
    Has Books: 
    3
    4
    5
    6
    Person name: 8
    Has Books: 
    7
    8
    9
    10
    Person name: 9
    Has Books: 
    11
      

  44.   

    上面我说错了Sorry,  需要的人的数量有可能大于文章的数量.
      

  45.   

    给个思路.假设结果是x个人,每个人能审核m篇文章.那么让每个人写m张"已阅"的纸条,放进x个抽屉里面.然后顺序从每个抽屉中拿一张纸条出来,凑够n张就算一篇文章过.(注意一定要顺序,到了末尾后又从第一个抽屉开始.)
    那么,
    1.当n<x时,能过的文章是0.所以必须有x>=n(此时也可保证到了末尾后不会重叠)
    2.其它情况下,会剩下的纸条最多不超过n张,此时可解得x个人至少能审核x*m-(n-1)篇文章,反解可推出x.
      

  46.   


    这个问题我觉得是在问两件事:首先是找人数,第二是找feasible solution. 其实如果把整个问题看成是个bipartite graph G(V,E), V = L + R,L = {所有文章}, R={所有人}, 两个节u \in L, v \in R点相连当切仅当v审u的文章.  G的特性就是所有L中节点的degree是n, 所有R中节点的degree是m. 如果通过两种方法数|E|, 那么有 |L|n = |R|m, 所以 |R| = sn/m。这就是所要的人数。这个人数肯定是不能变的,然后就是找feasible solution. 这个用简单的maximum flow就能算了。建构G’ = {s,t}+L+R, L = {所有文章}, R={所有人}。S与所有L节点相连, weight设为n; t与所有R节点相连, weight设为m; L,R中结点两两相连. 然后找s-t之间的最大流. 如果最大流不是n|L|, 那么就没有feasible solution. 如果想看bipartite graph和maximum flow, “Introduction to Algorithm”中有解释. 如果想看更难的network flow的问题, Robert Tarjan有一本”data-structure and network algorithm”. 不过network flow的东西可能operational research 的教材讲得更详细.
      

  47.   

    说错了....给楼上的楼上两星的人误导了.从新说一边,
    这个问题我觉得是在问两件事:首先是找人数,第二是找randome enough feasible solution.其实如果把整个问题看成是个 bipartite graph G(V,E), V = L + R,L = {所有文章}, R={所有人}, 两个节u \in L, v \in R点相连当切仅当v审u的文章. G的特性就是所有L中节点的degree是n, 所有R中节点的degree是m. 如果通过两种方法数|E|, 那么有 |L|n = |R|m, 所以 |R| = sn/m。这就是所要的人数。
    这个人数肯定是不能变的,然后就是找random feasible solution. 如果把上述的graph看成matrix, 那么他有跟matrix game差不多的特性,column sum 和row sum一样. 要让这个matrix random enough, 就一个一个column找解. 换一种说法,for 每一个人
    在还没被申完的论文中, 随便抽m篇
    next 下一个人还没被申完的论文意思为审此论文的人还不足n人.这样的random function collision肯定是有的.而存在两个人使得他们两个人审的论文相同的概率是(1/C(r, s))^2. C(r, s)指r选s. 只有在r跟s相同的情况下,才无解。而用polynomial trial可以让error rate降到可忽略的程度(=1/superpoly). 那位两星的回答,只是说明degenerated case不能解决。
      

  48.   

    还是说错了>.< 
    所有C(r, s)变成C(r,m), 无解的条件也说错了,我还没想到正确的条件。不过有点像submodular function....
      

  49.   

    不必求排列 
    只要求出最少人数p就可以了
    如果s<m
     p: 人数
     s*n=m*p
     求出P如果整数则是结果
     小数则取整加1即可
    如果 s>m
     则p=n
    由于题目不明确 我理解不必求出排列,排列的情况多了,有符合条件的,也有一个人重读文章的,
    但是对求最小人数没影响
    以上愚见 请指教
      

  50.   

    foren_whb(丰云) 已经说得很清楚了,偶的帖子也给出了比较容易理解的解法。作为程序员,逻辑思维和解决问题的能力是非常重要的,数学只是工具,别被忽悠了。
      

  51.   

    我已经解决,谢谢各位朋友.
    为了答谢各位朋友,可以去下面连接接分哦。
    http://community.csdn.net/Expert/topic/4931/4931648.xml?temp=.8525965
      

  52.   

    我觉得这道题目很有问题,每人审核m篇到底是必须审核m篇还是只能审核m篇,如果必须审核m篇,则会有s*n=m*x,而这个式子如果恒等,则大部分的情况都是无解的,并且这道题目根本就不用解。
      

  53.   

    dlzhangln(XXXXX)谁知道怎么改括号里的名