装箱算法的一种应用

// 1026.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
using namespace std;

// 单次下注记录
struct stBetInfoEx
{
    int index;
    int coinindex;
    int coinvalue;
    int coincount;
    int betuserid;
};

int _testIndex(int delta)
{
    static int vcoinvalue[5]={1,10,50,100,1000};
    for(int i=0;i<5;i++)
    {
        if(delta<vcoinvalue[i])
            return 2*i;
        if(delta==vcoinvalue[i])
            return 2*i+1;
    }
    return 10;
}

/*
    int coin0=_testCoin(0);//0
    int coin1=_testCoin(1);//1
    int coin2=_testCoin(4);//1
    int coin3=_testCoin(10);//10
    int coin4=_testCoin(11);//10
    int coin5=_testCoin(50);//50
    int coin6=_testCoin(60);//50
    int coin7=_testCoin(100);//100
    int coin8=_testCoin(110);//100
    int coin9=_testCoin(1000);//1000
    int coin10=_testCoin(1100);//1000
*/
int _Index2Idx(int ret)
{
    int idxs[11]={0,0,0,1,1,2,2,3,3,4,4};
    int idx=idxs[ret];
    return idx;
}

int _Index2Coin(int idx)
{
    static int vcoinvalue[5]={1,10,50,100,1000};
    int coin=vcoinvalue[idx];
    return coin;
}

int _testIdx(int delta)
{
    int ret=_testIndex(delta);
    int idx=_Index2Idx(ret);
    //cout<<"delta="<<delta<<","<<"ret="<<ret<<","<<"idx="<<idx<<endl;
    return idx;
}

int _testCoin(int delta)
{
    if(delta<=0)
        return 0;
    int idx=_testIdx(delta);
    int coin=_Index2Coin(idx);
    return coin;
}

int _getCoinIdx(int coin)
{
    static int vcoinvalue[5]={1,10,50,100,1000};
    for(int i=0;i<5;i++)
    {
        if(coin==vcoinvalue[i])
            return i;
    }
    return -1;
}

// 装箱算法:返回金币面值总和不大于max,且差值要尽可能的小
// 这里的币值类型保证了先装大的,再装小的,不存在50,50,50,70,70,max=150这种类型的装箱
vector<int> _combcoin(vector<int>& vCount,int max)
{
    static int vcoinvalue[5]={1,10,50,100,1000};
    
    vector<int> v;
    int sum=0;
    int lastcoin=0;
    while (sum<max)
    {
        int coin=_testCoin(max-sum);
        for(int i=4;i>=0;i--)
        {
            if(vCount[i]==0||vcoinvalue[i]>coin)
                continue;
            vCount[i]--;
            lastcoin=_Index2Coin(i);
            sum+=lastcoin;
            v.push_back(lastcoin);
            break;
        }
    }
    if(sum>max)
    {
        vector<int>::iterator iter=find(v.begin(),v.end(),lastcoin);
        if(iter!=v.end())
        {
            v.erase(iter);
        }
        int idx=_getCoinIdx(lastcoin);
        vCount[idx]++;
    }

    return v;
}

int gettotal(const vector<stBetInfoEx>& vIn)
{
    int n=vIn.size();
    int total=0;
    for (int i = 0; i < n; i++)
    {
        stBetInfoEx ex=vIn[i];
        total+=ex.coinvalue*ex.coincount;
    }
    return total;
}

void _dofun(vector<stBetInfoEx>& vIn,vector<int>& vDeltaCount)
{
    int total=gettotal(vIn);
    cout<<"total="<<total<<",";
    for(int i=0;i<vDeltaCount.size();i++)
    {
        int coin=_Index2Coin(i);
        while (vDeltaCount[i]>0)
        {
            for(int j=vIn.size()-1;j>=0;j--)
            {
                if(vIn[j].coincount==0||vIn[j].coinvalue!=coin)
                    continue;
                int mincount=(vDeltaCount[i]<vIn[j].coincount?vDeltaCount[i]:vIn[j].coincount);
                vDeltaCount[i]-=mincount;
                vIn[j].coincount-=mincount;
                if(vDeltaCount[i]==0)
                    break;
            }
            int a=0;
        }
    }
    int total1=gettotal(vIn);
    cout<<"total1="<<total1<<endl;
}

// 续投算法:能投多少是多少
vector<stBetInfoEx> _get_batchbet_result(const vector<stBetInfoEx>& vIn,int max)
{
    vector<stBetInfoEx> vOut=vIn;
    vector<int> vCount(5);
    int values[5]={1,10,50,100,1000};
    vector<int> vcoinvalue(5);

    for(int i=0;i<5;i++)
        vcoinvalue[i]=values[i];

    int n=vIn.size();
    int total=0;
    for (int i = 0; i < n; i++)
    {
        stBetInfoEx ex=vIn[i];
        vCount[ex.coinindex]+=ex.coincount;
        total+=ex.coinvalue*ex.coincount;
    }

    int totalcoincount= accumulate(vCount.begin(), vCount.end(),0);

    if(total<=max)
        return vOut;

    vector<int> vCount0=vCount;
    vector<int> vcoin=_combcoin(vCount,max);
    int total1= accumulate(vcoin.begin(), vcoin.end(),0);
    vector<int> vNewCount(5);
    for(int i=0;i<5;i++)
        vNewCount[i]=vCount0[i]-vCount[i];

    _dofun(vOut,vCount);

    return vOut;
}

int _tmain(int argc, _TCHAR* argv[])
{
    stBetInfoEx arrIn[]={
        {1,1,10,4,101871},
        {1,2,50,1,101871},        
        {1,0,1,10,101871},    
        {2,3,100,5,101871},
        {3,3,100,5,101871},
        {4,1,10,4,101871},
        {4,0,1,10,101871},
    };
    int max1=1149;
    int max2=89;

    int iItemCount=sizeof(arrIn)/sizeof(arrIn[0]);

    vector<stBetInfoEx> vIn(arrIn,arrIn+iItemCount);
    vector<stBetInfoEx> vOut1=_get_batchbet_result(vIn,max1);
    vector<stBetInfoEx> vOut11=_get_batchbet_result(vOut1,max1);
    vector<stBetInfoEx> vOut2=_get_batchbet_result(vIn,max2);
    vector<stBetInfoEx> vOut22=_get_batchbet_result(vOut2,max2);

    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值