递归思路:这里的原问题即为solve(a, n, 0, m),即这2n种组合中是否有和为m的,其中的子问题就是solve(a, n, i, m),即在确定了前i个元素下其后面的元素能否组合出m。然后将solve(a, n, i, m)分治为:solve(a, n, i+1, m)和solve(a, n, i+1, m-a[i]),即每个子问题都将其分治为其下一个元素的选或不选,这样就可以递归实现了。
Exhaustive Search
Write a program which reads a sequence A of n elements and an integer M,and outputs "yes"if you can make M by adding elements in A, otherwise "no". You can use an element only once.
You are given the sequence A and q questions where each question contains Mi.
Input
In the first line n is given. In the second line, n integers are given. In the third line q is given. Then, in the fourth line, q integers (Mi) are given.
Output
For each question Mi, print yes or no.
Constraints
n ≤ 20
q ≤ 2001 ≤ elements in A ≤ 20001 ≤ Mi ≤ 2000
Sample Input 151571021824178222110035
Sample Output 1
no
no
yes
yes
yes
yes
no
no
Notes
You can solve this problem by a Burte Force approach. Suppose solve(p, t) is a function which checkes whether you can make t by selecting elements after p-th element (inclusive). Then you can recursively call the following functions:solve(0, M)solve(1, M-{sum created from elements before 1st element})solve(2, M-{sum created from elements before 2nd element})...
The recursive function has two choices: you selected p-th element andnot. So, you can check solve(p+1, t-A[p])andsolve(p+1, t) in solve(p, t) to check the all combinations.
For example, the following figure shows that 8 can be made by A[0]+ A[2].
代码块
#include<iostream>usingnamespace std;intsolve(int*a,int n,int i,int m){if(m==0)//从输入值m中减去所选元素,当m==0就说明和为m,搜索成功。return1;if(i>=n)//i代表所选元素的个数,达到n就返回0,代表不成功return0;int res =solve(a, n, i+1, m)||solve(a, n, i+1, m-a[i]);//模拟a中第i+1个元素的选与不选:左边的代表不选,右边的代表选。如果某种情况中有1就返回1,都是0就返回0。return res;}intmain(void){int i, n, q;
cin>>n;int a[n];for(i=0; i<n; i++)
cin>>a[i];
cin>>q;for(i=0; i<q; i++){int m;
cin>>m;if(solve(a, n,0, m))
cout<<"yes"<<endl;else
cout<<"no"<<endl;}return0;}