C++ 微信红包数额分配的一种实现方法

      红包作为微信的一个重要功能,具有很高的可玩性。

经过观察,发现微信红包具有以下特点:

(1) 各人抢到的红包金额的总值严格等于发红包人所发的金额;

(2) 抢到红包的人最少抢到1分钱;

(3) 红包金额小于红包份数*1分时,发送红包失败;

(4) 每个人抢到的金额基本符合均值分布。

算法思路如下:

将总金额视为一条线段,分红包实际上就是在线段上取N-1个分割点,得到N条子线段,每条子线段的长度即为红包的金额。

算法实现如下:

将分红包算法实现为动态库。可以根据具体需要决定是否将红包函数放入单独库中。

#ifndef _HELPERFUNCS_H_
#define _HELPERFUNCS_H_
#include <vector>
/*******************************************************************************/
/*
 * Function Name : CalculateRedPacketValue
 * Parameters :
 *              int nTotalValue : [in] Total money to put into red packet, unit is FEN;
 *              int nNums       : [in] Number of red packets;
 *              std::vector<int>& vNodes : [out] money in every red packet;
 * Return Value:
 *              0 : Calculate successful;
 *             -1 : Total money should > 0;
 *             -2 : Number of red packets should > 0;
 *             -3 : Each red packet should have 1 fen at least;
 * Remark:
 *     Treat the total money as a line, put into 2 red packet means determine 1 
 * slit point, 3 red packet means 2 slit point.
 *     So the problem becomes into slit a line to N fragment by N-1 slit point.
/*******************************************************************************/
int CalculateRedPacketValue(int nTotalValue, int nNums, std::vector<int> & vNodes);
#endif
#include "HelperFuncs.h"
#include <map>
#include <stdlib.h>
#include <ctime>

/*******************************************************************************/
/*
 * Function Name : CalculateRedPacketValue
 * Parameters :
 *              int nTotalValue : [in] Total money to put into red packet, unit is FEN;
 *              int nNums       : [in] Number of red packets;
 *              std::vector<int>& vNodes : [out] money in every red packet;
 * Return Value:
 *              0 : Calculate successful;
 *             -1 : Total money should > 0;
 *             -2 : Number of red packets should > 0;
 *             -3 : Each red packet should have 1 fen at least;
 * Remark:
 *     Treat the total money as a line, put into 2 red packet means determine 1 
 * slit point, 3 red packet means 2 slit point.
 *     So the problem becomes into slit a line to N fragment by N-1 slit point.
/*******************************************************************************/
int CalculateRedPacketValue(int nTotalValue, int nNums, std::vector<int> & vNodes)
{
	if (nTotalValue <= 0) return -1;//Total money should > 0
	if (nNums <= 0) return -2;      //Number of red packets should > 0
	if (nTotalValue < nNums) return -3;//a red packet should have 1 fen at least
    
    //std::map will sort its key,so we make the value of red packet as the key
    //and we don't care about the value of a pair in the map; 
    std::map<int,int> mValue;

    srand((unsigned int)time(NULL));
    
    mValue.insert(std::pair<int,int>(0,1));//the begin point of the line
    mValue.insert(std::pair<int,int>(nTotalValue,1));//the end point of the line
    //determine the slit point
    while(mValue.size() < nNums+1)//care about the count of slit points
    {
        int temp =rand() % (nTotalValue-1) +1;//the value should in the range of [1,total mony -1]
        if (mValue.find(temp) != mValue.end() )//make sure the slit point is a new point 
        {
            continue;
        }
        mValue.insert(std::pair<int,int>(temp,1));//put into the map
    }
    vNodes.clear();
    std::map<int,int>::iterator itor = mValue.begin();
    std::map<int,int>::iterator itor_1;
    itor++;
    while (itor != mValue.end())//calculate the length of fragments 
    {
        itor_1 = --itor;
        itor++;
        vNodes.push_back(itor->first - itor_1->first);
        itor++;
    }
    return 0;
}
//调用分红包库的示例
#include "HelperFuncs.h"
#pragma comment(lib,"HelpFuncs.lib")
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> vNode;
    int x = CalculateRedPacketValue(20000,5,vNode);
    switch(x)
    {
    case -1:
        std::cout << "红包总金额需要大于0"<< std::endl;
        break;
    case -2:
        std::cout << "红包总份数需要大于0"<< std::endl;
        break;
    case -3:
        std::cout << "红包总金额需要大于总份数"<< std::endl;
        break;
    default:
        for (size_t i = 0; i < vNode.size(); i++)
        {
            std::cout <<"Value  : " << i <<" : " <<vNode[i]<< std::endl;
        }
        break;
    }

    return 0;
}

测试将20000分钱放入5个红包的结果如下:

放入1个红包结果如下:



将10分钱放入10个红包结果如下:

放入9个红包结果如下:

经过初步验证,红包金额之和与个数均符合要求。

猜你喜欢

转载自blog.csdn.net/freehawkzk/article/details/80158220