Algorithm of stealing red envelopes

Source: Internet
Author: User

Recently concerned about the CSDN programmer small Gray, the first two days sent a red envelope algorithm looked also quite interesting, their own use C implementation! (PS: Later found already Rotten street ... o (╥﹏╥) o)

Rules:

1. The sum equal to the amount of the bonus is not exceeded or less than
2. Everyone has at least one penny to rob.
3. Make sure everyone has the same odds of getting the amount.

Be prepared first:

#include <stdio.h>#include<stdlib.h>#include<time.h>#defineRandom (x) (rand ()%x)structnode{floatMoney ; structNode *Next;}; typedefstructNode *List; List createlist ();voidADD (floatCurrent, List *Last );intFind (intMoney , List L);voidSort (List L);voidprintlist (List L);voidALGORITHM1 (floatMoneyintnum, List L);voidALGORITHM2 (floatMoneyintnum, List L);voidALGORITHM3 (floatMoneyintnum, List L);intMain () {List L=createlist (); //Algorithm1 (100,10,l); //Algorithm2 (n, M, L); //printlist (L);ALGORITHM3 ( -,Ten, L);}    List createlist () {list L; L= (List)malloc(sizeof(List)); L->next =NULL; returnL;}voidADD (floatCurrent,list *Last ) {List L= (List)malloc(sizeof(List)); L->money =Current ; L->next =NULL; (*last)->next =L; (*last) =L;}intFind (intmoney,list L) {List ptr= l->Next;  while(PTR) {if(Ptr->money = =Money ) {            return 1; } ptr= ptr->Next; }    return 0;}voidSort (list L) {List cur= NULL, tail =NULL; Cur= l->Next;  while(cur->next!=tail) {        intFlag =1;  while(Cur->next! =tail) {            if(Cur->money > cur->next->Money ) {                floatTMP = cur->Money ; Cur->money = cur->next->Money ; Cur->next->money =tmp; Flag=0; } cur= cur->Next; }        if(flag) Break; Tail= cur;//The end node of the next traversal is the current node (carefully pondering the lane inside)Cur = l->next;//traverse the starting node to reset to the head node.    }}voidprintlist (list L) {list ptr= l->Next; inti =0;  while(PTR) {printf ("amount of people in the%d draw:%.2f\n", ++i,ptr->Money ); PTR= ptr->Next; }}
View Code

Three algorithms were spoken.

1. The first one is the wrong thing to say , also write a good contrast

Each time a random number of the remaining amount of the 0.01~ is taken as the amount of the current person, and when the last person extracts, the remaining amount is given to him.
Analysis:
Suppose 10 people, red envelope amount 100 yuan
The first person: the Random range (0,100), the average can grab 50 yuan
The second person: the Random range (0,50), the average can grab 25 yuan
Third Person: Random range (0,25), average can get 12.5 yuan
And so on, every random range is getting smaller.

voidALGORITHM1 (floatMoneyintnum, List L) {List last=L; Srand ((int) Time (0));//set the random number seed without setting the same random number every time    intCurrentmoeny = Money * -;//multiply the amount by 100 to get an integer     while(num>1){                intTMP = random (currentmoeny-1)+1;//guaranteed minimum random number of 1ADD (TMP/100.0,&Last ); Currentmoeny-= TMP;//Update Current Balancenum--; } Add (Currentmoeny/100.0, &last);//the last person to draw the remaining amount}
View Code

As a result, there are too many of the first people to rob ...

2. Twice-fold mean value method

Remaining red envelope amount M, number of remaining N, then: Amount per grab = random (0,m/n*2)
The average value of each random amount is guaranteed to be fair.
Suppose 10 people, red envelope amount 100 yuan
First person: 100/10*2=20, Random Range (0,20), average can get 10 yuan
Second person: 90/9*2=20, Random Range (0,20), average can get 10 yuan
Third Person: 80/8*2=20, Random Range (0,20), average can grab 10 yuan
And so on, the mean value of each random range is equal
Cons: In addition to the last time, any amount of money will not exceed the per capita amount of twice times, is not arbitrary random

voidALGORITHM2 (floatMoneyintnum, List L) {List last=L; Srand ((int) Time (0));//set the random number seed without setting the same random number every time    intCurrentmoeny = Money * -;//multiply the amount by 100 to get an integer     while(num>1) {        intMon = (currentmoeny/num) *2; intTMP = random (mon-1) +1;//guaranteed minimum random number of 1ADD (TMP/100.0, &Last ); Currentmoeny-= TMP;//Update Current Balancenum--; } Add (Currentmoeny/100.0, &last);//the last person to draw the remaining amount}
View Code

The result is a look, uh ... Much better, but I would like to have a person more some cards good or not ... o (* ̄︶ ̄*) o

3. Segment Segmentation method

Think of the total amount of red envelopes as a very long line segment, and the amount of each person to rob is the main section of the broken out of a number of sub-segments.

When n people Rob red envelopes together, it is necessary to determine N-1 a cutting point.

Therefore, when n individuals rob the total amount of the red envelope of M, we need to do a N-1 random operation, in order to determine the N-1 cutting point.

The random range is (1, M). When all the cut points are determined, the length of the sub-segments is also determined. So everyone to rob red envelopes, only need to pick up the length of the sub-segment and the equivalent amount of red envelopes.

This is the idea of segment cutting method. Here are the two points to note:

(1) When the random cutting point appears repeated, how to deal with the---repeat the cut again
(2) How to minimize the complexity of time and space complexity---here I use the list, sacrifice time for Space (ordered), can also sacrifice space saving time (large Array)

voidALGORITHM3 (floatMoneyintnum, List L) {List last=L; Srand ((int) Time (0));//set the random number seed without setting the same random number every timeADD (0, &last);//Initial Point    intCurrentmoeny = Money * -;//multiply the amount by 100 to get an integer     while(num>1) {//produce a N-1 point        intTMP = random (Currentmoeny-1) +1;//guaranteed minimum random number of 1        if(Find (tmp, L) = =0) {//The point does not existADD (TMP, &Last ); Num--; }} Add (Currentmoeny,&last);//End PointSort (L); inti =0; List ptr= l->Next;  while(ptr->Next) {List tmp= ptr->Next; intMoney = tmp->money-ptr->Money ; printf ("amount of people in the%d draw:%.2f\n", ++i, money/100.0); PTR= ptr->Next; }}
View Code

Bitter Ah, in order to save space there is no large array, need to take a bubble platoon order O (n^2) is gone, ε= (′ο ' *))) Alas, you can also optimize a little bit: each time after the random number, inserted sequentially into the list, so that saves the sorting time

For example, the time complexity is O (n^2), before one more order so is: O (n^2) +o (n^2):

intInsert (floatMoney , List L) {List ptr= l->Next;  while(ptr->Next) {        if(Ptr->next->money = =Money ) {            return 0; }        Else if(Ptr->next->money >Money ) {List tmp= (List)malloc(sizeof(List)); TMP->money =Money ; TMP->next = ptr->Next; PTR->next =tmp; return 1; } ptr= ptr->Next; } Add (Money,&AMP;PTR);//current list maximum value added to the last    return 1;}voidALGORITHM3 (floatMoneyintnum, List L) {List last=L; Srand ((int) Time (0));//set the random number seed without setting the same random number every time    intCurrentmoeny = Money * -;//multiply the amount by 100 to get an integerAdd (0, &last);//Initial PointADD (Currentmoeny, &last);//End Point         while(num>1) {//produce a N-1 point        intTMP = random (Currentmoeny-1) +1;//guaranteed minimum random number of 1//if (Find (TMP, L) ==0) {//The point does not exist//ADD (TMP, &last); //num--; //}            if(Insert (tmp, L) = =1) {num--; }    }        /*Sort (L);*/    inti =0; List ptr= l->Next;  while(ptr->Next) {List tmp= ptr->Next; intMoney = tmp->money-ptr->Money ; printf ("amount of people in the%d draw:%.2f\n", ++i, money/100.0); PTR= ptr->Next; }}
View Code

The result, uh ... It's much more comfortable to watch. Sleep ~

Welcome to The Spit slot! (*^▽^*)

Algorithm of stealing red envelopes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.