这是个装箱问题的变种。
上一个版本已经给出了求最优值的方法。
这个版本给出求出最优解。
思路就是在最优值的基础上,用分治法去找所有可能解。相当于回溯的方法进行最大化的剪枝。
代码如下:
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; }