给定一个非负数组A和非负数M,求出数组A中和最接近M的元素

这是个装箱问题的变种。

上一个版本已经给出了求最优值的方法。

这个版本给出求出最优解。

思路就是在最优值的基础上,用分治法去找所有可能解。相当于回溯的方法进行最大化的剪枝。

代码如下:

DestinationSum.h

#ifndef DESTINATIONSUM_H
#define DESTINATIONSUM_H

#include <string>
#include <vector>

using namespace std;

struct BestValue
{
    int bestV;
    size_t multiSolution;
};

class DestinationSum
{
public:
    DestinationSum();
    ~DestinationSum();

    void execute(vector<int>& data,int sum,vector<vector<int> >& result,size_t max_solution=1);
    void execute(vector<int>& data,int sum,string& result,size_t max_solution=1);
    void execute(vector<double>& data,double sum,vector<vector<double> >& result,bool isMultiSolution=false,size_t max_solution=1);
    void execute(vector<double>& data,double sum,string& result,bool isMultiSolution=false,size_t max_solution=1);

    void release();

private:
    void backtrace(double current_sum,int level);
    void backtrace(vector<vector<BestValue> >& bestV,int level,int sum,vector<bool>& result,size_t max_solution);

    vector<bool> m_solution;
    vector<vector<bool> > m_result;

    vector<double> m_datad;
    vector<double> m_datasumd;
    double m_sumd;
    double m_bestd;
    double m_real_bestd;
    bool m_isMultiSolutiond;
    bool m_isSingleSolutiond;
    size_t m_back_maxsolution;

    vector<int> m_datai;
    int m_sumi;

    vector<vector<BestValue> > bestV;
    size_t m_max_solution;
    size_t m_debug;
};

#endif

DestinationSum.cpp

#include "DestinationSum.h"
#include <algorithm>

DestinationSum::DestinationSum()
{
}

DestinationSum::~DestinationSum()
{
}

void DestinationSum::release()
{
    vector<bool>().swap(m_solution);
    vector<vector<bool> >().swap(m_result);
    vector<double>().swap(m_datad);
    vector<double>().swap(m_datasumd);
    vector<int>().swap(m_datai);
    vector<vector<BestValue> >().swap(bestV);
}

void DestinationSum::execute(vector<double>& data,double sum,vector<vector<double> >& result,bool isMultiSolution,size_t max_solution)
{
    //初始化
    m_result.clear();
    m_solution.resize(data.size(),false);

    result.clear();
    m_datad=data;
    m_sumd=sum;
    m_back_maxsolution=max_solution;
    m_max_solution=0;

    m_bestd=-1;

    //排序
    sort(m_datad.begin(),m_datad.end(),greater<int>());
    m_datasumd.resize(m_datad.size(),0);
    m_datasumd[m_datasumd.size()-1]=m_datad[m_datad.size()-1];
    for(int i=m_datad.size()-2;i>=0;i--)
    {
        m_datasumd[i]=m_datasumd[i+1]+m_datad[i];
    }

    if(isMultiSolution)
    {
        m_isMultiSolutiond=false;
        m_isSingleSolutiond=false;
        backtrace(0,0);
        m_real_bestd=m_bestd;
        m_isMultiSolutiond=true;
        //再次初始化
        m_bestd=-1;
        backtrace(0,0);
    }
    else
    {
        m_result.resize(1);
        m_isSingleSolutiond=true;
        m_isMultiSolutiond=false;
        backtrace(0,0);
    }

    for(int i=0;i<m_result.size();i++)
    {
        vector<double> oneResult;
        for(int j=0;j<m_result[i].size();j++)
        {
            if(m_result[i][j])
                oneResult.push_back(m_datad[j]);
        }
        result.push_back(oneResult);
    }
}

void DestinationSum::execute(vector<double>& data,double sum,string& result,bool isMultiSolution,size_t max_solution)
{
    vector<vector<double> > vector_result;
    execute(data,sum,vector_result,isMultiSolution,max_solution);

    result.clear();
    char num[256];
    
    //if(m_isMultiSolutiond)
    //    cout<<"满足的所有结果个数: "<<m_max_solution<<endl;

    if(m_isMultiSolutiond)
    {
        itoa(m_max_solution,num,10);
        result+="Total Solution = "+string(num)+"\n\n";
    }
    else
    {
        result+="Total Solution = Unknown\n\n";
    }
    for(int i=0;i<vector_result.size();i++)
    {
        double total=0;
        itoa(i+1,num,10);
        result+="[Solution"+string(num)+"] ";
        for(int j=0;j<vector_result[i].size();j++)
        {
            sprintf(num,"%f",vector_result[i][j]);
            total+=vector_result[i][j];
            result=result+string(num)+" ";
        }
        result+="\n";
        sprintf(num,"%f",total);
        result+="Sum: "+string(num);
        result+="\n\n";
    }
}

void DestinationSum::backtrace(double current_sum,int level)
{
    if(current_sum>=m_sumd || level==m_datad.size())
    {
        if(m_bestd<0 || abs(current_sum-m_sumd)<=m_bestd)
        {
            m_bestd=abs(current_sum-m_sumd);

            if(m_isMultiSolutiond && m_real_bestd==m_bestd)
                m_max_solution++;

            if(m_isMultiSolutiond && m_real_bestd==m_bestd && m_result.size()<m_back_maxsolution)
            {
                m_result.push_back(m_solution);
            }
            else if(m_isSingleSolutiond)
            {
                m_result[0]=m_solution;
            }
        }
    }
    else if(current_sum+m_datasumd[level]<=m_sumd)
    {
        current_sum+=m_datasumd[level];
        if(m_bestd<0 || abs(current_sum-m_sumd)<=m_bestd)
        {
            m_bestd=abs(current_sum-m_sumd);
            for(int i=level;i<m_solution.size();i++)
            {
                m_solution[i]=true;
            }

            if(m_isMultiSolutiond && m_real_bestd==m_bestd)
                m_max_solution++;

            if(m_isMultiSolutiond && m_real_bestd==m_bestd && m_result.size()<m_back_maxsolution)
            {
                m_result.push_back(m_solution);
            }
            else if(m_isSingleSolutiond)
            {
                m_result[0]=m_solution;
            }

            for(int i=level;i<m_solution.size();i++)
            {
                m_solution[i]=false;
            }
        }
    }
    else if(current_sum<m_sumd && current_sum+m_datasumd[level]>m_sumd )
    {
        backtrace(current_sum,level+1);

        m_solution[level]=true;
        backtrace(current_sum+m_datad[level],level+1);
        m_solution[level]=false;
    }
}

void DestinationSum::execute(vector<int>& data,int sum,vector<vector<int> >& result,size_t max_solution)
{
    m_solution.resize(data.size(),false);

    result.clear();
    m_result.clear();
    m_sumi=sum;
    m_datai=data;
    m_max_solution=0;
    m_debug=0;
    vector<vector<BestValue> >().swap(bestV);

    int count=data.size();
    bestV.resize(count);
    for(int i=0;i<count;i++)
    {
        bestV[i].resize(sum+1);
    }
    for(int i=0;i<=sum;i++)
    {
        bestV[count-1][i].bestV=min(i,abs(data[count-1]-i));
        
        //存储解个数
        if(i==abs(data[count-1]-i))
        {
            bestV[count-1][i].multiSolution=2;
        }
        else
        {
            bestV[count-1][i].multiSolution=1;
        }
    }

    for(int i=count-2;i>0;i--)
    {
        for(int j=0;j<=sum;j++)
        {
            int i_value=abs(data[i]-j);
            if(data[i]>=j)
            {
                bestV[i][j].bestV=min(i_value,bestV[i+1][j].bestV);

                //存储解个数
                if(i_value==bestV[i+1][j].bestV)
                {
                    bestV[i][j].multiSolution=bestV[i+1][j].multiSolution+1;
                }
                else
                {
                    if(i_value<bestV[i+1][j].bestV)
                    {
                        bestV[i][j].multiSolution=1;
                    }
                    else
                    {
                        bestV[i][j].multiSolution=bestV[i+1][j].multiSolution;
                    }
                }
            }
            else
            {
                bestV[i][j].bestV=min(bestV[i+1][j].bestV,bestV[i+1][j-data[i]].bestV);

                //存储解个数
                if(bestV[i+1][j].bestV==bestV[i+1][j-data[i]].bestV)
                {
                    bestV[i][j].multiSolution=bestV[i+1][j].multiSolution+bestV[i+1][j-data[i]].multiSolution;
                }
                else
                {
                    if(bestV[i+1][j].bestV<bestV[i+1][j-data[i]].bestV)
                    {
                        bestV[i][j].multiSolution=bestV[i+1][j].multiSolution;
                    }
                    else
                    {
                        bestV[i][j].multiSolution=bestV[i+1][j-data[i]].multiSolution;
                    }
                }
            }
        }
    }
    if(count>1)
    {
        if(data[0]<=sum)
        {
            bestV[0][sum].bestV=min(bestV[1][sum].bestV,bestV[1][sum-data[0]].bestV);
            //存储解个数
            if(bestV[1][sum].bestV==bestV[1][sum-data[0]].bestV)
            {
                bestV[0][sum].multiSolution=bestV[1][sum].multiSolution+bestV[1][sum-data[0]].multiSolution;
            }
            else
            {
                if(bestV[1][sum].bestV<bestV[1][sum-data[0]].bestV)
                {
                    bestV[0][sum].multiSolution=bestV[1][sum].multiSolution;
                }
                else
                {
                    bestV[0][sum].multiSolution=bestV[1][sum-data[0]].multiSolution;
                }
            }
        }
        else
        {
            int i_value=data[0]-sum;
            bestV[0][sum].bestV=min(i_value,bestV[1][sum].bestV);
            //存储解个数
            if(i_value==bestV[1][sum].bestV)
            {
                bestV[0][sum].multiSolution=bestV[1][sum].multiSolution+1;
            }
            else
            {
                if(i_value<bestV[1][sum].bestV)
                {
                    bestV[0][sum].multiSolution=bestV[1][sum].multiSolution;
                }
                else
                {
                    bestV[0][sum].multiSolution=1;
                }
            }
        }
    }

    m_max_solution=bestV[0][sum].multiSolution;

    vector<bool> tmp_result;
    backtrace(bestV,0,sum,tmp_result,max_solution);

    for(int i=0;i<m_result.size();i++)
    {
        vector<int> oneResult;
        for(int j=0;j<m_result[i].size();j++)
        {
            if(m_result[i][j])
                oneResult.push_back(m_datai[j]);
        }
        result.push_back(oneResult);
    }
}


void DestinationSum::backtrace(vector<vector<BestValue> >& bestV,int level,int sum,vector<bool>& result,size_t max_solution)
{
    if(level==m_datai.size()-1)
    {
        if(bestV[level][sum].bestV==sum)
        {
            m_debug++;
            result.push_back(false);
            if(m_result.size()<max_solution)
                m_result.push_back(result);
            result.pop_back();
        }

        if(bestV[level][sum].bestV==abs(m_datai[level]-sum))
        {
            m_debug++;
            result.push_back(true);
            if(m_result.size()<max_solution)
                m_result.push_back(result);
            result.pop_back();
        }

        return;
    }
    
    if(bestV[level][sum].bestV==bestV[level+1][sum].bestV)
    {
        result.push_back(false);
        backtrace(bestV,level+1,sum,result,max_solution);
        result.pop_back();
    }
    
    if(sum>=m_datai[level] && bestV[level][sum].bestV==bestV[level+1][sum-m_datai[level]].bestV)
    {
        result.push_back(true);
        backtrace(bestV,level+1,sum-m_datai[level],result,max_solution);
        result.pop_back();
    }

    if(sum<m_datai[level] && bestV[level][sum].bestV==m_datai[level]-sum)
    {
        vector<bool> tmp_result;
        tmp_result.resize(m_datai.size(),false);
        tmp_result[level]=true;
        m_debug++;
        if(m_result.size()<max_solution)
            m_result.push_back(tmp_result);
    }
}

void DestinationSum::execute(vector<int>& data,int sum,string& result,size_t max_solution)
{
    vector<vector<int> > vector_result;

    execute(data,sum,vector_result,max_solution);

    result.clear();
    char num[256];

    //cout<<"满足的所有结果个数: "<<m_max_solution<<" "<<m_debug<<endl;
    
    itoa(m_max_solution,num,10);
    result+="Total Solution = "+string(num)+"\n\n";

    for(int i=0;i<vector_result.size();i++)
    {
        int total=0;
        itoa(i+1,num,10);
        result+="[Solution"+string(num)+"] ";
        for(int j=0;j<vector_result[i].size();j++)
        {
            sprintf(num,"%d",vector_result[i][j]);
            total+=vector_result[i][j];
            result=result+string(num)+" ";
        }
        result+="\n";
        sprintf(num,"%d",total);
        result=result+"Sum: "+string(num);
        result+="\n\n";
    }
}

main.cpp

#include <DestinationSum.h>

#define ARRAY 264,13340,18340,5000,14020,29060,9780,22194,21820,2460,20520,2460,2460,2460,11560,22630,4920,7000,26880,18260,25216,28620,28520,4240,10000,16220,4240,12000,3200,12916,2250,9834,2460,4860,984,11360,26760,6396,9840,3444,4860
#define SUM 158500

int main(int argc,char *argv[])
{
    //vector<double> data;
    //
    //double a[]={ARRAY};
    //for(int i=0;i<sizeof(a)/sizeof(double);i++)
    //{
    //    data.push_back(a[i]);
    //}
    //DestinationSum ds;
    //string str;
    //ds.execute(data,SUM,str,true,50);
    //cout<<str;

    vector<int> data1;
    int a1[]={ARRAY};
    for(int i=0;i<sizeof(a1)/sizeof(int);i++)
    {
        data1.push_back(a1[i]);
    }
    DestinationSum ds1;
    string str1;
    ds1.execute(data1,SUM,str1,3);
    cout<<str1;
    system("pause");
    return 0;
}
posted @ 2013-04-19 12:08  风中精灵LvFQ  阅读(332)  评论(0编辑  收藏  举报