Combination Sum II

来源:互联网 发布:js 设置div可见 编辑:程序博客网 时间:2024/05/16 01:05

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

For example, given candidate set 10,1,2,7,6,1,5 and target 8
A solution set is: 
[1, 7] 
[1, 2, 5] 
[2, 6] 
[1, 1, 6] 

利用01背包,另外减枝。注意减枝尽量多。

开始由于未加 if(target < 0 ) return; 结果导致严重超时,即使代码是对的。但是由于他任然在遍历所有可能,但是不退出。最小面给出测试用例,可以发现,超时即为严重!

#include <iostream>#include <vector>#include <algorithm>using namespace std;void combine_sum(vector<int> &candidate,int target,int level ,vector<bool> &used,vector<int> res_one,vector<vector<int>> &res);vector<vector<int>>  combine_sum_final(vector<int> &candidate,int target);int main(){vector<int> candidate;int target;int temp;cin >> temp;while (temp >= 0){candidate.push_back(temp);cin >> temp;}cout<<endl;cin>>target;vector<vector<int>> res;res = combine_sum_final(candidate,target);cout<<"res:" <<res.size()<<endl;for (int i = 0 ;i < res.size();i++){for (int j = 0;j <res[i].size();j++){cout<< res[i][j]<<" ";}cout<<endl;}}vector<vector<int>>  combine_sum_final(vector<int> &candidate,int target){sort(candidate.begin(),candidate.end());//<span style="color:#cc0000;">先排序</span>if (target == 0 || candidate.size() == 0 || candidate[0] <= 0){return vector<vector<int>>();}vector<int>  res_one;vector<vector<int>> res;vector<bool> used(candidate.size(),false);combine_sum(candidate,target,0,used,res_one,res);return res;}//需保证target 非0 !!  01 背包加减枝void combine_sum(vector<int> &candidate,int target,int level ,vector<bool> &used,vector<int> res_one,vector<vector<int>> &res){ if(target < 0 ) return; if (level >= candidate.size()) { if (target == 0) { res.push_back(res_one); } return ; } bool uesd_falg = true;/* for(int i = 0;i < level;i++) {if (candidate[i] == candidate[level] && (!used[i])){uesd_falg = false;break;} }*/  //对付未排序的for(int i = level-1;i >= 0 && candidate[i] == candidate[level];i--)//排序了的{if (!used[i]){uesd_falg = false;}}if(uesd_falg)//加入前判断{res_one.push_back(candidate[level]);used[level] =  true;combine_sum(candidate,target-candidate[level],level+1,used,res_one,res);res_one.pop_back();used[level] =  false;}combine_sum(candidate,target,level+1,used,res_one,res);//不加入分支}

第二次:
 vector<vector<int> > combinationSum2(vector<int> &num, int target) {                return combine_sum_final(num,target);    }    vector<vector<int>>  combine_sum_final(vector<int> &candidate,int target)    {sort(candidate.begin(),candidate.end());if (target == 0 || candidate.size() == 0 || candidate[0] <= 0){return vector<vector<int>>();}vector<int>  res_one;vector<vector<int>> res;vector<bool> used(candidate.size(),false);combine_sum(candidate,target,0,used,res_one,res);return res;    }void combine_sum(vector<int> &candidate,int target,int level ,vector<bool> &used,vector<int> res_one,vector<vector<int>> &res){ if(target < 0 ) return; if (level >= candidate.size()) { if (target == 0) { res.push_back(res_one); } return ; } bool uesd_falg = true;//写法也是对的,后面想想发现没必要依次往前看,只需看前一个,应为如果连续几个111 重复,010,001这种情况在前面已减枝,//后面只需判断101此种if(level > 0 && candidate[level-1] == candidate[level] && !used[level-1]) uesd_falg = false;if(uesd_falg)//加入前判断{res_one.push_back(candidate[level]);used[level] =  true;combine_sum(candidate,target-candidate[level],level+1,used,res_one,res);res_one.pop_back();used[level] =  false;}combine_sum(candidate,target,level+1,used,res_one,res);}

//10 1 2 7 6 1 5 -1
//12

//14 6 25 9 30 20 33 34 28 30 16 12 31 9 9 12 34 16 25 32 8 7 30 12 33 20 21 29 24 17 27 34 11 17 30 6 32 21 27 17 16 8 24 12 12 28 11 33 10 32 22 13 34 18 12 -1(用于结束输入)

// 结果:27

0 0