红包作为微信的一个重要功能,具有很高的可玩性。
经过观察,发现微信红包具有以下特点:
(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个红包结果如下:
经过初步验证,红包金额之和与个数均符合要求。