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