zoukankan      html  css  js  c++  java
  • 给定一个非负数组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;
    }
  • 相关阅读:
    spring boot banner设置关闭以及关闭特定的自动配置
    spring boot 初始及快速搭建
    spring scheduling 计划任务
    idea database 导入实体带注解
    idea mapper下的方法找不到 Invalid bound statement (not found)
    spring jwt token 认证
    spring event 事件
    FrontEnd-Basis-6th
    FrontEnd-Basis-5th
    FrontEnd-Basis-4th
  • 原文地址:https://www.cnblogs.com/lvfq/p/3030400.html
Copyright © 2011-2022 走看看